Giter VIP home page Giter VIP logo

labs's Introduction

moq

Version Downloads Discord Chat Sponsors

The most popular and friendly mocking library for .NET

  var mock = new Mock<ILoveThisLibrary>();

  // WOW! No record/replay weirdness?! :)
  mock.Setup(library => library.DownloadExists("2.0.0.0"))
      .Returns(true);

  // Use the Object property on the mock to get a reference to the object
  // implementing ILoveThisLibrary, and then exercise it by calling
  // methods on it
  ILoveThisLibrary lovable = mock.Object;
  bool download = lovable.DownloadExists("2.0.0.0");

  // Verify that the given method was indeed called with the expected value at most once
  mock.Verify(library => library.DownloadExists("2.0.0.0"), Times.AtMostOnce());

Moq also is the first and only library so far to provide Linq to Mocks, so that the same behavior above can be achieved much more succinctly:

  ILoveThisLibrary lovable = Mock.Of<ILoveThisLibrary>(l =>
    l.DownloadExists("2.0.0.0") == true);

  // Exercise the instance returned by Mock.Of by calling methods on it...
  bool download = lovable.DownloadExists("2.0.0.0");

  // Simply assert the returned state:
  Assert.True(download);
  
  // If you want to go beyond state testing and want to 
  // verify the mock interaction instead...
  Mock.Get(lovable).Verify(library => library.DownloadExists("2.0.0.0"));

You can think of Linq to Mocks as "from the universe of mocks, give me one whose behavior matches this expression".

Check out the Quickstart for more examples!

What?

Moq (pronounced "Mock-you" or just "Mock") is the only mocking library for .NET developed from scratch to take full advantage of .NET Linq expression trees and lambda expressions, which makes it the most productive, type-safe and refactoring-friendly mocking library available. And it supports mocking interfaces as well as classes. Its API is extremely simple and straightforward, and doesn't require any prior knowledge or experience with mocking concepts.

Why?

The library was created mainly for developers who aren't currently using any mocking library (or are displeased with the complexities of some other implementation), and who are typically manually writing their own mocks (with more or less "fanciness"). Most developers in this situation also happen to be quite pragmatic and adhere to state (or classic) TDD. It's the result of feeling that the barrier of entry from other mocking libraries is a bit high, and a simpler, more lightweight and elegant approach is possible. Moq achieves all this by taking full advantage of the elegant and compact C# and VB language features collectively known as LINQ (they are not just for queries, as the acronym implies).

Moq is designed to be a very practical, unobtrusive and straight-forward way to quickly setup dependencies for your tests. Its API design helps even novice users to fall in the "pit of success" and avoid most common misuses/abuses of mocking.

When it was conceived, it was the only mocking library that went against the generalized and somewhat unintuitive (especially for novices) Record/Replay approach from all other libraries (and that might have been a good thing ;)).

Not using Record/Replay also means that it's straightforward to move common expectations to a fixture setup method and even override those expectations when needed in a specific unit test.

You can read more about the "why" and see some nice screenshots at kzu's blog.

Where?

See our Quickstart examples to get a feeling of the extremely simple API and install from NuGet.

Read about the announcement at kzu's blog. Get some background on the state of mock libraries from Scott Hanselman.

In-depth documentation is being added to the documentation website.

Who?

Moq was originally developed by Clarius, Manas and InSTEDD.

Moq uses Castle DynamicProxy internally as the interception mechanism to enable mocking.

Features at a glance

Moq offers the following features:

  • Strong-typed: no strings for expectations, no object-typed return values or constraints
  • Unsurpassed VS IntelliSense integration: everything supports full VS IntelliSense, from setting expectations, to specifying method call arguments, return values, etc.
  • No Record/Replay idioms to learn. Just construct your mock, set it up, use it and optionally verify calls to it (you may not verify mocks when they act as stubs only, or when you are doing more classic state-based testing by checking returned values from the object under test)
  • VERY low learning curve as a consequence of the previous three points. For the most part, you don't even need to ever read the documentation.
  • Granular control over mock behavior with a simple MockBehavior enumeration (no need to learn what's the theoretical difference between a mock, a stub, a fake, a dynamic mock, etc.)
  • Mock both interfaces and classes
  • Override expectations: can set default expectations in a fixture setup, and override as needed on tests
  • Pass constructor arguments for mocked classes
  • Intercept and raise events on mocks
  • Intuitive support for out/ref arguments

We appreciate deeply any feedback that you may have! Feel free to participate in the chat, or report an issue in the issue tracker.

Sponsors

Clarius Org Kirill Osenkov MFB Technologies, Inc. Stephen Shaw Torutek DRIVE.NET, Inc. Ashley Medway Keith Pickford Thomas Bolon Kori Francis Toni Wenzel Giorgi Dalakishvili Uno Platform Dan Siegel Reuben Swartz Jacob Foshee Eric Johnson Ix Technologies B.V. David JENNI Jonathan Oleg Kyrylchuk Charley Wu Jakob Tikjøb Andersen Seann Alexander Tino Hager Mark Seemann Ken Bonny Simon Cropp agileworks-eu sorahex Zheyu Shen Vezel ChilliCream 4OTC

Sponsor this project  

Learn more about GitHub Sponsors

labs's People

Contributors

adalon avatar blairconrad avatar kzu avatar stakx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

labs's Issues

Does not compile in VS Community 2017 - The target "GitVersion" does not exist in the project

If you simply download the ZIP file, extract to a folder, double-click the .sln file to run it in Visual Studio, then right-click "Solution (Moq) (3 projects)" at the top and do a Rebuild Solution, you get:

1>------ Rebuild All started: Project: Moq, Configuration: Debug Any CPU ------
1>U:\Visual Studio 2017\Projects\Moq\build\GitVersion.props(14,109): error MSB4057: The target "GitVersion" does not exist in the project.
1>Done building project "Moq.csproj" -- FAILED.
1>U:\Visual Studio 2017\Projects\Moq\build\GitVersion.props(14,109): error MSB4057: The target "GitVersion" does not exist in the project.
1>Done building project "Moq.csproj" -- FAILED.
2>------ Rebuild All started: Project: Moq.Tests, Configuration: Debug Any CPU ------
3>------ Rebuild All started: Project: Moq.Tests.VisualBasic, Configuration: Debug Any CPU ------
========== Rebuild All: 0 succeeded, 3 failed, 0 skipped ==========

With 2 errors in the Error List:
Severity Code Description Project File Line Suppression State
Error MSB4057 The target "GitVersion" does not exist in the project. Moq U:\Visual Studio 2017\Projects\Moq\build\GitVersion.props 14
Error MSB4057 The target "GitVersion" does not exist in the project. Moq U:\Visual Studio 2017\Projects\Moq\build\GitVersion.props 14

I don't have "Git" installed, and this could be why, but which version am I supposed to install, and how? NuGet? Compile it from GitHub? Installer? Which version do I need?

Add support for autocomplete

Steps to Reproduce

  1. Create a new setup for a mocked class.
  2. Tap Cltr+Space inside the parenthesis the method.
  3. The autocomplete should offer one line per overload of that method.

Expected Behavior

See this archived repository:
https://github.com/Litee/moq.autocomplete

See the readme of the project above.

Actual Behavior

No autocomplete currently

Add support for custom manual mocks in VB

A NRE deep inside Roslyn is being thrown when we run the VB codefixes in the context of a manual mock that wants to implement IStunt.

The whole analyzer/codefix for VB has been disabled for now as a consequence (for custom mocks)

Feature request: create mocks without requiring empty constructor/passing parameters

Would it be possible to not throw exceptions when creating mocks of types with non-default parameters?

I know you can pass arguments, but it's not strongly typed to the constructor being called.

FakeItEasy doesn't require the arguments to be passed. I suspect it's using FormatterServices.GetUninitializedObject() under the hood, although I don't know if that's in .NET core.

I had a conversation about this many years ago on the mailing list where Krzysztof Koźmic said it wouldn't be possible with Castle at the time, but I did a proof of concept ProxyFactoryFactory back then and managed to create objects without running the ctor, so I think it can be done.

Steps to Reproduce

public class X  
{
    public X(string y){     }
} 

 new Moq.Mock<X>().Object.ToString(); // 

 
### Expected Behavior

The mock is created without throwing an exception. 

### Actual Behavior

throws "InvalidProxyConstructorArgumentsException:  Can not instantiate proxy of class: UserQuery+X.Could not find a parameterless constructor.

--


 

Moq generic fails

For some reason when using generic methods to setup mocks the generics fail. I don't understand why mocked proxy objects can't be passed as arguments.
`
// works
var mock = new Mock<IGrantOpeningService>();
// Run this in the watch - mock.Object.GetGrantOpening(1);
// Returns null

// doesn't work
Setup<IGrantOpeningService>();
public void Setup<T>() where T : class
{
var mock = new Mock<T>();
// Run this in the watch - mock.Object.GetGrantOpening(1);
// Throws exception that the method doesn't exist
}

// also doesn't work
var mock = new Mock<IGrantOpeningService>();
// Run this in the watch - mock.Object.GetGrantOpening(1)
// Returns null
Setup(mock);
public void Setup<T>(Mock<T> mock)
{
// Do something
// Run this in the watch - mock.Object.GetGrantOpening(1)
// Throws exception that the method doesn't exist
}
`

Xunit: Moq Setup doesn't return expected value

Hi, everyone.
I've implemented a service that sends sms to some devices by means of AWS SNS Service.
The service checks for each device if it exists in a whitelist table. If the device isn't found, the sms is sent to a fallback number.

So, I've a WhiteListUser class:

public class WhiteListUser
{
    [Key]
    public string Device { get; set; }

    public string Username { get; set; }

    public bool IsFallback { get; set; }
}

An application context :

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }

    public DbSet<WhiteListUser> WhiteListUsers { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.Entity<WhiteListUser>().HasData(new WhiteListUser
        {
            Device = "+39370XXXXXXX",
            Username = "FALLBACK",
            IsFallback = true
        });
    }
}

and the service:

public interface ISmsService
{
    Task<IList<SendSmsResponse>> SendSmsAsync(SendSms @event, CancellationToken token);
}

public class SNSService : ISmsService
{
    private readonly IAwsProvider _awsProvider;
    private readonly ILogger<SNSService> _logger;
    private readonly IHostEnvironment _environment;
    private readonly IGenericRepository<WhiteListUser> _repository;

    public SNSService(IHostEnvironment environment, IGenericRepository<WhiteListUser> repository, IAwsProvider awsProvider, ILogger<SNSService> logger)
    {
        _awsProvider = awsProvider;
        _logger = logger;
        _environment = environment;
        _repository = repository;
    }

    public async Task<IList<SendSmsResponse>> SendSmsAsync(SendSms @event, CancellationToken cancellationToken)
    {
        if (_environment.IsDevelopment())
        {
            var fallbackNumber = (await _repository.Find(u => u.IsFallback)).First().Device;
            int i = 0;
            while (i < @event.Devices.Count)
            {
                var device = @event.Devices[i];
                var users = await _repository.Find(u => u.Device == device);
                if (users?.ToList().Count == 0)
                {
                    @event.Devices[i] = fallbackNumber;
                }
                i++;
            }
        }
        var response = await _awsProvider.SendSmsAsync(@event.Devices, @event.Message, cancellationToken);
        return response;
    }
}

SendSms event is a record with a message and a list of devices:

public record SendSms
{
    public string Message { get; set; }
    public List<string> Devices { get; set; }
}

When I try to run this test, it fails:

public class SNSServiceTest
{
    private readonly ISmsService _sut;
    private readonly Mock<IAwsProvider> _awsProviderMoq;
    private readonly Mock<ILogger<SNSService>> _loggerMoq;
    private readonly Mock<IHostEnvironment> _hostEnvironmentMoq;
    private readonly Mock<IGenericRepository<WhiteListUser>> _repositoryMoq;

    public SNSServiceTest()
    {
        _awsProviderMoq = new Mock<IAwsProvider>();
        _loggerMoq = new Mock<ILogger<SNSService>>();
        _hostEnvironmentMoq = new Mock<IHostEnvironment>();
        _repositoryMoq = new Mock<IGenericRepository<WhiteListUser>>();

        _sut = new SNSService(_hostEnvironmentMoq.Object,
                              _repositoryMoq.Object,
                              _awsProviderMoq.Object,
                              _loggerMoq.Object);
    }

   

    [Fact]
    public async Task Does_Replace_Only_Not_In_Whitelist_Numbers_With_Fallback_In_Dev_Env()
    {
        // Arrange
        var @event = new SendSms
        {
            Message = "pippo",
            Devices = new List<string>
            {
                "unknown",
                WhiteListFixtures.FallbackUser.Device,
                WhiteListFixtures.WhiteListUser.Device
            }
        };

        _repositoryMoq
          .Setup(x => x.Find(c => c.IsFallback))
          .ReturnsAsync(new List<WhiteListUser> { WhiteListFixtures.FallbackUser });

        _repositoryMoq
           .Setup(x => x.Find(c => c.Device == WhiteListFixtures.FallbackUser.Device))
           .ReturnsAsync(new List<WhiteListUser> { WhiteListFixtures.FallbackUser });

        _repositoryMoq
          .Setup(x => x.Find(c => c.Device == WhiteListFixtures.WhiteListUser.Device))
          .ReturnsAsync(new List<WhiteListUser> { WhiteListFixtures.WhiteListUser });

        _hostEnvironmentMoq.Setup(x => x.EnvironmentName).Returns(Environments.Development);

        // Act
        await _sut.SendSmsAsync(@event, CancellationToken.None);

        // Assert
        _awsProviderMoq
            .Verify(x => x.SendSmsAsync(
                It.Is<IList<string>>(l => l.Count == 3 &&
                                          l[0].Equals(WhiteListFixtures.FallbackUser.Device) &&
                                          l[1].Equals(WhiteListFixtures.FallbackUser.Device) &&
                                          l[2].Equals(WhiteListFixtures.WhiteListUser.Device)),
                "pippo",
                CancellationToken.None));
    }
}

where Fixtures are:

public class WhiteListFixtures
{

public static WhiteListUser FallbackUser => new WhiteListUser
{
    Device = _fallbackNumber,
    Username = "Test1",
    IsFallback = true,
};

public static WhiteListUser WhiteListUser = new WhiteListUser
{
    Device = _whiteListNumber,
    Username = "Test2",
    IsFallback = false,
};

private static string _fallbackNumber = "+393701002134";
private static string _whiteListNumber = "+393702223344";

}

it seems that these two setups are not working, so devices are never found and all the devices are so replaced, also the third one that is in the whitelist:

        _repositoryMoq
           .Setup(x => x.Find(c => c.Device == WhiteListFixtures.FallbackUser.Device))
           .ReturnsAsync(new List<WhiteListUser> { WhiteListFixtures.FallbackUser });

        _repositoryMoq
          .Setup(x => x.Find(c => c.Device == WhiteListFixtures.WhiteListUser.Device))
          .ReturnsAsync(new List<WhiteListUser> { WhiteListFixtures.WhiteListUser });

this is the error message:

UnitTests.Services.SNSServiceTest.Does_Replace_Only_Not_In_Whitelist_Numbers_With_Fallback_In_Dev_Env
 Source: SNSServiceTest.cs line 34
 Duration: 11 ms

Message: 
Moq.MockException :
Expected invocation on the mock at least once, but was never performed: x => x.SendSmsAsync(It.Is<IList>(l => ((l.Count == 3 && l[0].Equals(WhiteListFixtures.FallbackUser.Device)) && l[1].Equals(WhiteListFixtures.FallbackUser.Device)) && l[2].Equals(WhiteListFixtures.WhiteListUser.Device)), "pippo", CancellationToken)

Performed invocations:

MockIAwsProvider:2 (x):

  IAwsProvider.SendSmsAsync(["+39370XXXXXXX", "+39370XXXXXXX", "+39370XXXXXXX"], "pippo", CancellationToken)

Stack Trace: 
Mock.Verify(Mock mock, LambdaExpression expression, Times times, String failMessage) line 330
Mock1.Verify[TResult](Expression1 expression) line 810
SNSServiceTest.Does_Replace_Only_Not_In_Whitelist_Numbers_With_Fallback_In_Dev_Env() line 67
--- End of stack trace from previous location ---

I don't know what am I doing wrong, if the test or the implementation.
I was expecting: IAwsProvider.SendSmsAsync(["+39370XXXXXXX", "+39370XXXXXXX", "+39370YYYYYYY"], "pippo", CancellationToken)

Can any expert help me?
Thanks in advance

Can't install Moq NuGet on UWP

Hello,

I'm currently having the problem that I can't install Moq in a UWP UnitTestApp project. It is the only project type that can be used to unit test an uwp app.

Moq says on NuGet that it is compatible with .NetStandard 1.3 which should be compatible with UWP when looking at this table: https://docs.microsoft.com/en-us/dotnet/standard/net-standard

I'm getting the following error while Installing the Package:

Restoring packages for UnitTestProject1\project.json...
System.Reflection.Emit.ILGeneration 4.3.0 provides a compile-time reference assembly for System.Reflection.Emit.ILGeneration on UAP,Version=v10.0.10586, but there is no run-time assembly compatible with win10-arm-aot.
System.Reflection.Emit.ILGeneration 4.3.0 provides a compile-time reference assembly for System.Reflection.Emit.ILGeneration on UAP,Version=v10.0.10586, but there is no run-time assembly compatible with win10-x64-aot.
System.Reflection.Emit.ILGeneration 4.3.0 provides a compile-time reference assembly for System.Reflection.Emit.ILGeneration on UAP,Version=v10.0.10586, but there is no run-time assembly compatible with win10-x86-aot.
Package restore failed. Rolling back package changes for 'UnitTestProject1'.
Time Elapsed: 00:00:01.3615812
========== Finished ==========

When I try to install the package System.Reflection.Emit.ILGeneration on its own I get the same error.

Greetings
Gary

How can I build this project on mac os x?

I have a problem when I try to build this project, I received the following message:

Microsoft (R) Build Engine version 16.0.42-preview+g804bde742b for Mono
Copyright (C) Microsoft Corporation. All rights reserved.

MSBUILD : error MSB1028: The logger failed unexpectedly.
System.TypeInitializationException: The type initializer for 'Colorful.Console' threw an exception. ---> System.EntryPointNotFoundException: GetStdHandle
  at (wrapper managed-to-native) Colorful.ColorMapper.GetStdHandle(int)
  at Colorful.ColorMapper.GetBufferColors () [0x00007] in <8bd381b5fce54663ae8ff03962192106>:0 
  at Colorful.Console..cctor () [0x00184] in <8bd381b5fce54663ae8ff03962192106>:0 
   --- End of inner exception stack trace ---

Add support for logging via Mock

By default when you create new Mock object - it allows to record methods being called, by placing them into "Invocations" property.

I would prefer to operate in real time and perform logging of methods being called and their call arguments.

By brief check of Moq v4 - I've noticed that this is far not simple thing to be done, as Moq does use Castle.DynamicProxy.ProxyGenerator, but it does not allow end-user of Moq to override call with it's own interceptor.

What I've came up - is maybe I could just double proxy executing - so Moq would create one proxy and I would put second proxy on top of that one.

    public class LoggedMock<T>: Mock<T> where T: class
    {
        object logProxy;

        Castle.DynamicProxy.ProxyGenerator proxygenerator;
        string[] _methodsToIgnore;

        public LoggedMock(
            params string[] methodsToIgnore
        ) : base()
        {
            _methodsToIgnore = methodsToIgnore;
        }


        public override T Object
        {
            get
            {
                if (logProxy == null)
                {
                    if (proxygenerator == null)
                    { 
                        proxygenerator = new Castle.DynamicProxy.ProxyGenerator();
                    }

                    if (typeof(T).IsInterface)
                    {
                        logProxy = proxygenerator.CreateInterfaceProxyWithTarget(typeof(T), base.Object, new LoggedMockInterceptor(_methodsToIgnore));
                    }
                    else
                    { 
                        logProxy = proxygenerator.CreateClassProxyWithTarget(typeof(T), base.Object, new LoggedMockInterceptor(_methodsToIgnore));
                    }
                }

                return (T)logProxy;
            }
        }

This did work correctly, however - then I wanted to switch from Mock<interface> to Mock<abstract class> - and then noticed that Mock does support such method as As<TInterface>(), which in a turn woul create a new copy of Mock with different generic parameter.

To support all use cases as Mock does - it would require also mimic also class AsInterface<TInterface> : LoggedMock<TInterface>
class, which drags more complexity into whole story.

Moverover - then I've noticed that Moq v5 was not based anymore on Castle core, with it's own mechanisms for logging interception.

Also if interception is done via logging - it's possible also to override existing Mock behavior and not to update Invocations at all (as it would eat more performance).

Just to illustrate what kind of logging I want to achive - this is something coded with Castle.Core / Moq v4.

    public class LoggedMockInterceptor : IInterceptor
    {
        StringBuilder sb = new StringBuilder();
        string[] _methodsToIgnore;

        public LoggedMockInterceptor(string[] methodsToIgnore)
        {
            _methodsToIgnore = methodsToIgnore;
        }

        public void Intercept(IInvocation invocation)
        {
            string name = invocation.Method.Name;

            if (_methodsToIgnore.Contains(name))
            {
                //invocation.Proceed();
                return;
            }

            ParameterInfo[] parameters = invocation.Method.GetParameters();
            sb.Clear();

            object[] args = invocation.Arguments;
            sb.Append(name);
            sb.Append("(");

            for (int i = 0; i < parameters.Length; i++)
            {
                if (i != 0)
                {
                    sb.Append(",");
                }

                if (parameters[i].ParameterType == typeof(string))
                {
                    if (args[i] == null)
                    {
                        sb.Append("null");
                    }
                    else
                    { 
                        sb.Append("\"");
                        sb.Append(args[i].ToString());
                        sb.Append("\"");
                    }
                }
                else
                { 
                    sb.Append(args[i].ToString());
                }
            }
            
            sb.Append(")");
        
            LogService.GetInstance(false)._console.Info(sb.ToString());
            invocation.Proceed();
        }
    }

Would it be possible to add into Moq v5 logging support or just to provide some code on how this could be done.

Adding `Callback` to a mock breaks async tests

I have the following csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>

    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
    <PackageReference Include="Moq" Version="4.10.0" />
    <PackageReference Include="xunit" Version="2.3.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
  </ItemGroup>

</Project>

and the following test class:

    public class SomeComponentTest
    {
        private readonly SomeComponent _someComponent;
        private readonly Mock<ISomeDependency> _someDependency;

        public SomeComponentTest()
        {
            _someDependency = new Mock<ISomeDependency>();
            _someComponent = new SomeComponent(_someDependency.Object);
        }

        [Fact]
        public async Task Should_do_stuff()
        {
            _someDependency
                .Setup(x => x.DoMoreStuffAsync())
                // .Returns(Task.CompletedTask) // (line X)
                .Callback(() =>
                {
                    /*do nothing*/
                });

            await _someComponent.DoStuffAsync();
        }
    }

    public interface ISomeDependency
    {
        Task DoMoreStuffAsync();
    }

The test fails because DoMoreStuffAsync returns null which breaks async state machine generated by C# compiler. Uncommenting line that I called line X solves the problem.

In my opinion async methods should be treated specially by mock, and generally they should never return null (as this is certainly a mistake).

Expected behavior: When I define a callback on an async method it should by default return Task.CompletedTask to the caller so that it will not break async code.

_

_

Moq does not mock 'Explicit Interface Implementation' and 'protected virtual' correctly

If we use Explicit Interface Implementation, with same name as a protected virtual method, Moq will mock the wrong method.
Protected methods should not be possible to mock, due to their protection level.

We found this issue in one of our Custom HttpHandlers that inherits from HttpClientHandler.
The method we implement is a overridden protected virtual method SendAsync. To be able to mock this, we used a Interface method as a layer in between for calling base (do an actual httprequest instead for just calling the mock).

Steps to Reproduce

Code example of code with this behaviour:

void Main()
{
    var mock = new Moq.Mock<Contract>() { CallBase = true };
    mock.As<IContractOveride>().Setup(m => m.DoWork()).Returns(3);
    Console.WriteLine(mock.Object.PublicWork()); //Writes out "3". Should be "1". Wrong method is mocked.
}

public class Contract : IContractOveride
{
    public int PublicWork()
    {
        return this.DoWork();
    }
    
    protected virtual int DoWork()
    {
        //Should not be able to mock this method: '...' is inaccessible due to its protection level
        ((IContractOveride)this).DoWork(); //Does not return the value of interface method.
        return 1;
    }

    int IContractOveride.DoWork()
    {
        Console.WriteLine("IFace");
        return 2;
    }
}

public interface IContractOveride
{
    int DoWork();
}

Working code:

void Main()
{
    var mock = new Moq.Mock<Contract>() { CallBase = true };
    mock.As<IContractOveride>().Setup(m => m.DoWorkOverride()).Returns(3);
    Console.WriteLine(mock.Object.PublicWork()); //Writes out "1" as expected
}

public class Contract : IContractOveride
{
    public int PublicWork()
    {
        return this.DoWork();
    }
    
    protected virtual int DoWork()
    {
        //Should not be able to mock this method: '...' is inaccessible due to its protection level
        ((IContractOveride)this).DoWorkOverride(); //Does not return the value of interface method.
        return 1;
    }

    int IContractOveride.DoWorkOverride()
    {
        Console.WriteLine("IFace");
        return 2;
    }
}

public interface IContractOveride
{
    int DoWorkOverride(); //This name is the only change.
}

Expected Behavior

It should write out "1" as i am overriding the interfaced method and not the virtual one.
The virtual method should not be mocked in any circumstances, as this one is protected.

Actual Behavior

It writes out "3" since it mocks the protected virtual method, and not the interfaced method.

GitHub Actions

I was wondering if you'd welcome a PR that incorporated actions for testing/releases and anything else moq requires.

Doesn't work on internal packages

E.g

import "/home/ammar/go/src/go.coder.com/sauce/internal/wss/plugins": cannot import absolute path
no initial packages were loaded

Add support for being able to proxy existing class instance

By default when you create new Mock, you cannot use existing class instance - meanwhile in Moq v 4 - I've noticed that Castle.DynamicProxy.ProxyGenerator supports providing existing class instance - you can use either CreateInterfaceProxyWithTarget or CreateClassProxyWithTarget - and proxy existing class instance.

I do understand that Moq v5 is slightly different than Moq v4 - but I think its possible to use same concept as well.

So maybe there should be alternative constructor:

class Mock<T>...

      Mock(T t);  // Use by default all methods from t unless overridden by Setup function call.

Which would allow to pass class instance to be proxied.

This feature would be useful in case if want to use majority of same functionality as T defines, by maybe override by couple of methods via Setup.

`Stringly.cs` doesn't format all types correctly

This is probably low-priority, as it might affect mostly diagnostic messages, and not Moq's core functionality.

The Stringly class in both Stunts and Moq.Sdk supposedly formats Type objects to a C# representation, but there are several cases where it doesn't work as it should. Here's just a few examples (there are probably more):

class A { }

class A<T>
{
    public class B<U> { }
}

[Theory]
[InlineData( typeof(A[][,]),           "A[][,]"           )] // => actual: "A[,][]"
[InlineData( typeof(A<object>[]),      "A<object>[]"      )] // => actual: "A`1[]"
[InlineData( typeof(A<>),              "A<>"              )] // => actual: "A`1"
[InlineData( typeof(A<object>.B<int>), "A<object>.B<int>" )] // => actual: "A`1.B<object>"
public void Stringly_ToTypeName_formats_correctly(Type type, string expected)
{
    Assert.Equal(expected, Stringly.ToTypeName(type));
}

I'm aware that Stringly probably doesn't have to be perfect, and that you might not be interested in fixing every single corner case (many might be relevant in a mocking scenario).

However, if you do want to improve Stringly: I'm currently working on a standalone library to do much the same of what Stringly does; see stakx/TypeNameFormatter. It covers the above corner cases, and then some more. I'm aiming at turning this into a NuGet package eventually (possibly a source-only one). If you're interested in reusing this effort in some way, let me know.

Documentation

I'm just wondering where I can find documentation for this framework?

Edit: I did eventually find it in the Moq4 repo - but this was after going to this repo, the github site, and some other pages. It might be nice to have links to the v4 wiki from here and the github site.

Moq v5

Pendings:

  • Interface proxies
  • Abstract class proxies
  • Allow customizing the proxy generation
  • Consume the generator Sdk from Moq.Sdk to inject IMocked interface
  • Override all virtual members
  • Add design-time proxies support via analyzers and code fixes
  • Add support for updating out-of-date proxies (analyzer + codefix)
  • Returns
  • Callbacks
  • Events
  • Throws
  • Setup void methods
  • Default value for Task/Task
  • Overridable default value behavior
  • Named mocks
  • Make debugging and inspecting mocks and their state awesome
  • Recursive mocks
  • Verify
  • Verifiable
  • All Moq v4 features available in v5
  • Linq to Mocks @marianor
  • Stunts nuget package via NuGetizer
  • Stunts.Sdk nuget package via NuGetizer
  • Moq.Sdk nuget package via NuGetizer
  • CI nuget feed with all packages
  • Analyzer/code fixes for legacy APIs via nuget
  • New website, maybe docfx? See https://www.dennisdel.com/how-we-build-documentation/. Autofac.org uses RTD...
  • Code coverage badge via coveralls.io
  • Bring back dynamic run-time proxies

Builds from a fresh clone are broken

Steps to Reproduce

  1. Clone the repository
  2. Run dotnet build Moq.sln from the src folder

Expected Behavior

The project builds.

Actual Behavior

Microsoft (R) Build Engine version 15.7.179.6572 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restoring packages for E:\Code\Buildalyzer\tests\repos\moq\src\Moq\Moq.Analyzer\Moq.Analyzer.csproj...
  Restoring packages for E:\Code\Buildalyzer\tests\repos\moq\src\Moq\Moq.Sdk.Tests\Moq.Sdk.Tests.csproj...
  Restoring packages for E:\Code\Buildalyzer\tests\repos\moq\src\Moq\Moq.Package\Moq.Package.nuproj...
  Restoring packages for E:\Code\Buildalyzer\tests\repos\moq\src\Moq\Moq.Sdk\Moq.Sdk.csproj...
C:\Program Files\dotnet\sdk\2.1.300\NuGet.targets(114,5): error : The local source 'C:\Users\dglick\AppData\Local\Temp\packages' doesn't exist. [E:\Code\Buildalyzer\tests\repos\moq\src\Moq.sln]

Build FAILED.

C:\Program Files\dotnet\sdk\2.1.300\NuGet.targets(114,5): error : The local source 'C:\Users\dglick\AppData\Local\Temp\packages' doesn't exist. [E:\Code\Buildalyzer\tests\repos\moq\src\Moq.sln]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:04.42

I noticed this problem while using Moq as an integration test for Buildalyzer. It's triggered on a fresh clone when no $(TEMP)\packages folder exists when building from the command line.

The root of the issue is that the LocalPublish target from Settings.targets is set to evaluate after the Pack target. However, the Restore target looks in the $(TEMP)\packages folder that the LocalPublish creates and populates. Since Restore runs before Pack (and thus LocalPublish), the folder doesn't exist for Restore when it's needed.

Add support for protected members

In v4:

mock.Protected().Setup("SendAsync", ...)

We should offer more compile-time safety in v5 for protected members, possibly with completion providers + analyzers

Raise(..) does not return event return values

Hi

I have the following code, it doesnt work.
Please fix :)

public delegate object TestDelegate();

public class TestClassWithEvent
{
    public virtual event TestDelegate TestEvent;
}

[Test]
public void UnitTest()
{
    var mock = new Mock<TestClassWithEvent>();
    mock.Object.TestEvent += () => "test";

    object[] returnValue = mock.Raise(_ => _.TestEvent += null);
    Assert.AreEqual(returnValue.Single(), "test");
}

Assert.Throws overloads for message verification and additional matching with expression

Hi,

Currently, Assert.Throws provides some overloads for ArgumentException.ParamName matching and a few other overloads.

My suggestion is for another overload to be added with an exception matcher expression overload, for flexible and customizable exception verification.

For example:

var expectedExceptionMessage = "My exception message";
var expectedException = new MyServiceException(expectedExceptionMessage);

Assert.Throws(expectedException, () => myService.DoJob());

// or

Assert.Throws(exception => exception.Message == expectedExceptionMessage);

Here are another couple of overloads I'd like to see (same for async and "Any" when applicable):

  • Assert.Throws(string message, Action testCode);
  • Assert.Throws(string message, string paramName, Action testCode);

I'm willing to implement this.

Failing to build on main

Cloning the repo and trying to build results in an error and multiple warnings:

warning NU1603: Moq.Sdk depends on Avatar (>= 42.42.42-main.434) but Avatar 42.42.42-main.434 was not found. An approximate best match of Avatar 42.42.42-main.492 was resolved.
error AV001: The current compiler uses Roslyn version 4.1.0 which is not supported yet. Please install package Microsoft.Net.Compilers.Toolset version 3.9.0 to get the latest supported compiler, or set 'EnableCompileTimeAvatars=false' in the project to switch to run-time avatars.

The warnings can be cleared up by changing the AvatarVersion in Directory.Packages.props to match the found version (42.42.42-main.492) and the initial error can be cleared by adding a reference to Microsoft.Net.Compilers.Toolset specifying the latest supported version (3.9.0).

Trying to build after fixing the initial problems results in errors with seemingly every class that implements IAvatarBehavior

error CS0246: The type or namespace name 'GetNextBehavior' could not be found (are you missing a using directive or an assembly reference?)
error CS0535: 'MockRecordingBehavior' does not implement interface member 'IAvatarBehavior.Execute(IMethodInvocation, ExecuteHandler)'

The GetNextBehavior delegate doesn't exist in this codebase, the closest I found was GetNextMockBehavior which has an additional IMock parameter which means the delegate doesn't match the ExecuteHandler for the interface.

Our open source team @opencastsoftware would like to contribute if possible but not sure where to go from here. If we can help in getting this fixed please let us know

Build: ensure that code generating tasks are idempotent

Looks like the build tasks writing files such as C:\moq\src\Stunts\Stunts\obj\Debug\ThisAssembly.ProjectProperties.g.cs will write the file even if the existing text content is exactly the same.

For proper incremental builds consider changing that logic so that it first reads the text from the file if it exists, compares, and only writes the text if it's different from what is already there.

There are issues against MSBuild to make these changes to the WriteLinesToFile and WriteCodeFragment tasks: dotnet/msbuild#3597

Simplify syntax for registering value provider factories

Currently you need to know to cast to IMocked get the IMock, access the behaviors, get the DefaultValueBehavior, and use its Provider property to register the factories. Hardly discoverable ;). We need an easier facade on top.

To have an interface Mock use existing implementation logic, devs should be able to provide an implementation class

This is a feature request for new Moq functionality. Something which comes up from time to time in testing is a scenario when I want to create an interface-based Mock object and - by default - I want its functionality to behave as if it were a real instance of an implementation class for that interface. I don't want to just provide an instance of that class though, because I also want to use some of Moq's functionality such as writing one or more setups or using a Verify to verify that a method was called with the correct params.

In this scenario what I would like would be a way to tell Mock:

Hey, I want a mock for interface IFoo, but for any functionality which I haven't explicitly set up, could you just behave as if you were an instance of ConcreteFoo?

In many ways, this is like setting CallBase to true for a class-based Mock, except that for interfaces, the developer needs to provide an impl. I'd expect to see it work in a very similar way; the matching functionality from the provided concrete impl would be executed and used, unless a setup matches the call to the mock.

Suggested syntax

Here's some suggested syntaxes and overloads for the functionality. The names UseDefaultImplementation and UseDefaultImplementationType are 100% up for grabs, I'm not precious about them at all.

In this case/overload, the dev must pass an instance of IFoo to the mock object directly. This function could reasonably use a generic type constraint to ensure that the impl instance passed is of type IFoo.

var mockObj = new Mock<IFoo>();
var defaultImpl = new ConcreteFoo();
mockObj.UseDefaultImplementation(defaultImpl);

In this case/overload, the dev indicates the implementation type to use and Moq takes control of creating the instance, perhaps just via Activator.CreateInstance, or via a generic type constraint on new(). It would also be totally reasonable to have a generic type constraint on IFoo here.

var mockObj = new Mock<IFoo>();
mockObj.UseDefaultImplementationType<ConcreteFoo>();

This overload would be functionally identical to the above, except non-generic. Obviously, the compiler wouldn't be able to use generic type constraints to ensure you provided a sane type.

var mockObj = new Mock<IFoo>();
mockObj.UseDefaultImplementationType(typeof(ConcreteFoo));

Generate API overloads for delegate-based setups

We currently provide an autofix that will add the generic delegate type to the Setup<T> call,
but it would be even better if the generic argument wasn't even needed. This could be achieved
by just generating additional overloads of Setup via extension methods.

Since overload resolution is performed on parameter types (and not return value type type), there
may be chances of conflicts in generated code. Maybe in those cases the type of the delegate is
just required to disambiguate?

Moq4 compiled in debug mode?

Hi Guys,

I am having issues with Moq4 as I recently moved up to it from Moq3 via NuGet, but it appears the NuGet package was compiled with debugging turned on so Visual Studio keeps trying to find the source files under the c:\projects\moq4 directory, which of course I do not have.

This is extremely annoying when trying to debug unit tests, so is there a way to turn this off or can the project be compiled in release mode with debugging information so it works the way it used to?

Deep verification of call arguments

When mocking a service interface, I want to make assertions that a method on the interface was called with a given set of arguments. Currently Moq lets me call Verify on my mock to check, but will only perform equality comparisons on expected and actual arguments using Equals. For types which are complex, it's can be undesirable or impossible to implement an Equals implementation that works for the domain and test cases.

Instead, I'm having to Setup my Moq in a way which captures the arguments so I can make assertions on them after asserting that a call has been made:

Bar actualBar = null;
var service = new Mock<IService>();
service
    .Setup(x => x.Foo(It.IsAny<Bar>())
    .Callback<Bar>(b => actualBar = b);

// ...Run the test...

// Assert the service was called once.
service.Verify(x => x.Foo(It.IsAny<Bar>(), Times.Once);

// Assert the service was given the correct information.
actualBar.ShouldBeEquivalentTo(expectedBar);

Is there some way to get access to the recorded invocations other than using Verify? Could there be a way to extend Verify to perform more complex assertions and report on failures more clearly?

Allow Access to Protected Class Members

Hi folks! 👋

Summary

As far as I know, Moq doesn't provide direct access to protected class members. You can call ProtectedExtension.Protected<T>(Mock<T> mock) to setup the mock's protected members, but you can't directly get/set protected properties/fields, and you can't directly call protected methods. This can make it difficult to mock a base class and test the base class's functionality.

Example

Suppose that you have the following:

public abstract class BaseClass {
    protected string _commonField;

    protected BaseClass() {
        _commonField = GetStringWithId("SomeId");
    }

    public string GetStringWithId(string id) {
        // Returns string with given ID.
    }
}

public class FirstImplementation : BaseClass  {
    public FirstImplementation() : base() { }

    public void SomeMethod() {
        // Uses _commonField.
    }
}

public class SecondImplementation : BaseClass {
    public SecondImplementation() : base() { }

    public void AnotherMethod() {
        // Uses _commonField
    }
}

Since _commonField is used by implementors, I would argue that you should create a unit test for the _commonField property. Ideally, you would do this by using the partial mock feature with BaseClass. This unit test would validate that _commonField is getting set correctly in the constructor; that way you can validate that the correct value is getting provided to FirstImplementation and SecondImplementation.

The concern is that Moq doesn't provide direct access to the _commonField field, so you can't verify that it is getting set correctly. Instead, you either have to (a) create your own mock or (b) use reflection.

Pin castle dependency in package

System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> System.TypeInitializationException : The type initializer for 'Moq.Mock`1' threw an exception.
  ----> System.TypeInitializationException : The type initializer for 'Moq.Proxy.CastleProxyFactory' threw an exception.
  ----> System.IO.FileLoadException : Could not load file or assembly 'Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Moq.Mock.SetupAllProperties(Mock mock, Stack`1 mockedTypesStack)
   at Moq.Mock.<>c__DisplayClass72_0.<SetupAllProperties>b__0()
   at Moq.PexProtector.Invoke(Action action)
   at Moq.Mock.SetupAllProperties(Mock mock)
   at Moq.Mock`1.SetupAllProperties()
   at Moq.Mocks.<CreateMocks>d__6`1.MoveNext()
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at Moq.Linq.MockQueryable`1.Execute[TResult](Expression expression)
   at Moq.Mock.Of[T]()
   at Gu.Reactive.Tests.Reflection.PropertyPathParserTests.GetPathFromMock() in C:\Git\Gu.Reactive\Gu.Reactive.Tests\Reflection\PropertyPathParserTests.cs:line 47
--TypeInitializationException
   at Moq.Mock`1.SetupGet[TProperty](Expression`1 expression)
--TypeInitializationException
   at Moq.Proxy.CastleProxyFactory..ctor()
   at Moq.Mock`1..cctor()
--FileLoadException
   at Moq.Proxy.CastleProxyFactory..cctor()

When checking nuget the castle dependency is Castle.Core (>= 4.0.0) it should be pinned to an exact version or the assembly loading should handle never versions of castle.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.