Git Product home page Git Product logo

pclmock's Introduction

Logo

PCLMock

Build status

What?

PCLMock is a lightweight, but powerful mocking framework targeting .NET Standard 1.0 (it was originally a Portable Class Library, hence the name).

Why?

At the time of inception, existing mocking frameworks (such as Moq) rely heavily on reflection and other mechanisms that are not available on more limited .NET runtimes, such as Mono. Writing mocks without the aid of a framework is laborious, error-prone, and results in inconsistent code. PCLMock aims to fill this gap.

Where?

The easiest way to get PCLMock is via NuGet:

Install-Package PCLMock

There are also packages specific to code generation.

How?

Mocks can be created automatically via code generation or manually. Generally speaking, you will want to use one of the code generation packages to generate the bulk of your mock implementation. If, instead, you want to define mocks manually, read the documentation on defining mocks.

Test code can utilize the mocks in various ways. Here is a typical example:

[Fact]
public void some_test()
{
    var mockService = new SomeServiceMock();
	mockService
	    .When(x => x.Login(It.IsAny<string>(), "123456"))
	    .Return(true);

    var sut = new Foo(mockService);

    // some test code here

    mockService
        .Verify(x => x.Login("me", "123456"))
        .WasNotCalled();
}

For a detailed discussion, read the documentation on using mocks.

Who?

PCLMock is created and maintained by Kent Boogaart. Issues and pull requests are welcome.

pclmock's People

Contributors

kentcb avatar reicheltp 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pclmock's Issues

It.Is is not always implicit when it should be

This works as expected:

var mock = new SomeMock();
mock.When(x => x.SomeMethod("foo")).Return("bar");

Assert.Equal("bar", mock.SomeMethod("foo"));

This does not:

var mock = new SomeMock();
var obj = new object();
mock.When(x => x.SomeMethod(obj)).Return("bar");

Assert.Equal("bar", mock.SomeMethod(obj));

It.Matches support

Add an It.Matches(Func<T, bool>) method. The function is called to determine whether the argument matches or not, thus giving the client code utmost flexibility. An example of usage:

var mock = ...;

mock.When(x => x.SomeMethod(It.Matches(i => i % 2 == 0)))
    .Return("Even");

mock.When(x => x.SomeMethod(It.Matches(i => i % 2 == 1)))
    .Return("Odd");

Assert.Equal("Even", mock.SomeMethod(2));
Assert.Equal("Even", mock.SomeMethod(223710));
Assert.Equal("Odd", mock.SomeMethod(1));
Assert.Equal("Odd", mock.SomeMethod(223713));

Consider generating mocks for types outside solution

There are times when it is useful to be able to have mocks for third party interfaces. The code generator does not currently provide a means of doing so. Perhaps it could also traverse third party assemblies and feed them into the generation pipeline.

Consider opening up loose behavior to consumers

Per #18, give some thought to whether it is possible+desirable to open up the loose behavior "pipeline" to consuming code. That is, allow client code to make sweeping decisions about loose behavior such as "for any method returning Task<T>, return Task.FromResult(default(T)) by default".

  • Define a hook interface (ISomethingSomething) in codegen assembly (also: consider an altogether separate SDK assembly)
  • Add the requisite functionality to the configuration, such that hooks can be configured
  • Have the code generator utilise the hooks when generating mocks
  • Write two standard hooks: one for TPL-based async members, and one for Rx-based async members
  • Update the default configuration file to include these standard hooks by default
  • Create new NuGet package: PCLMock.CodeGeneration that includes only the codegen assembly

Recursive application of plugins

Consider a means of recursively applying plugins. For example, consider the following interface:

public interface ISomeInterface
{
    IImmutableList<string> Stuff { get; }

    IObservable<IImmutableList<string>> GetMoreStuff();
}

The collections plugin will ensure the Stuff property defaults to ImmutableList<string>.Empty. The observables plugin will ensure GetMoreStuff returns Observable.Return(default(IImmutableList<string>)). But that default value will be null. If plugins were instead applied recursively (at the discretion of each plugin), it could ensure that GetMoreStuff returned Observable.Return(ImmutableList<string>.Empty) by default, which would be far more useful.

The serious challenge here is that the IPlugin interface is not designed to be fine-grained. It allows plugins to inject any code into the ConfigureBehavior and ConfigureLooseBehavior methods of a mock. As a consequence, each plugin is generating this.When calls for its own specific scenario. Designing a plugin interface that still allows a high degree of control by plugins, but also allows them to recursively invoke other plugins for fine-grained situations will be difficult.

Generated mocks for internal interfaces should be internal

A mock for an internal interface should be generated as internal class but it is generated as public class instead.

Example:
MyAssembly defines:

internal interface IService 
{
    void DoSomething();
}

I made the interfaces visible for my TestAssembly with [InternalsVisibleFor("MyAssembly.Tests"].
Now I aspect that the generated mock class looks the following:

in my MyAssembly.Tests assembly:

[System.CodeDom.Compiler.GeneratedCode("PCLMock", "4.0.0.0")]
[System.Runtime.CompilerServices.CompilerGenerated]
internal partial class ServiceMock : global::PCLMock.MockBase<global::MyAssembly.IService>, global::MyAssembly.IService    
{
    public ServiceMock (global::PCLMock.MockBehavior behavior = global::PCLMock.MockBehavior.Strict): base (behavior)
    {
        if ((behavior) == (global::PCLMock.MockBehavior.Loose))
        {
            ConfigureLooseBehavior();
        }
    }

    partial void ConfigureLooseBehavior();

...
}

Since they are not generated as internal I got an Inconsistent accessibility error.

Thanks for your help!

Best regards,
Paul

Cannot find System.Coposition.TypedParts

I just tried to use the T4 generator, but when I try to run the custom tool, I get following error:

Error   16  Running transformation: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AggregateException: One or more errors occurred. ---> System.IO.FileNotFoundException: Could not load file or assembly 'System.Composition.TypedParts, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
   at Microsoft.CodeAnalysis.Host.Mef.MefHostServices.Create(IEnumerable`1 assemblies)
   at Microsoft.CodeAnalysis.Host.Mef.DesktopMefHostServices.get_DefaultServices()
   at Kent.Boogaart.PCLMock.CodeGeneration.Generator.<GenerateMocksAsync>d__0.MoveNext() in C:\Users\kent\Repository\PCLMock\Src\Kent.Boogaart.PCLMock.CodeGeneration\Generator.cs:line 24
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Kent.Boogaart.PCLMock.CodeGeneration.XmlBasedGenerator.<GenerateMocksAsync>d__2.MoveNext() in C:\Users\kent\Repository\PCLMock\Src\Kent.Boogaart.PCLMock.CodeGeneration\XmlBasedGenerator.cs:line 48
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at Kent.Boogaart.PCLMock.CodeGeneration.XmlBasedGenerator.GenerateMocks(String solutionPath, String xmlPath, Language language) in C:\Users\kent\Repository\PCLMock\Src\Kent.Boogaart.PCLMock.CodeGeneration\XmlBasedGenerator.cs:line 29
   at Kent.Boogaart.PCLMock.CodeGeneration.XmlBasedGenerator.GenerateMocks(String solutionPath, String xmlPath, String language) in C:\Users\kent\Repository\PCLMock\Src\Kent.Boogaart.PCLMock.CodeGeneration\XmlBasedGenerator.cs:line 21
   --- End of inner exception stack trace ---
   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 Microsoft.VisualStudio.TextTemplating59389E350AC879AC2313AB3BF88249987D0426CB576DCFE492173DC732D3844164099E1D5EA5CD146FE3DD173ED128E47A71AAFFE3474AF69A3196EB6CD0079A.GeneratedTextTransformation.TransformText() in c:\Src\Strat\ConsoleApplication5\UnitTestProject1\Mocks.tt:line 19   c:\Src\Strat\ConsoleApplication5\UnitTestProject1\Mocks.tt  19  1   UnitTestProject1

It's .net 4.5 project

Improve evaluation behavior

Improve the evaluation behavior significantly. In addition to what is currently possible, the following should be possible:

// calling a method (FromSeconds) to obtain the value
mock.Verify(x => x.SomeMethod(TimeSpan.FromSeconds(1)))
    .WasCalledExactlyOnce();

// performing calculations
mock.Verify(x => x.SomeMethod((37 * 2) / 12))
    .WasCalledExactlyOnce();

Of course, the same should be true in the context of a When() call.

InvalidOperationException: Specifications against methods cannot be chained

I'm coming up against this exception for some test cases I'm trying to write. I'm deploying this to Xamarin with the xUnit device runner package. It's unclear to me why I'm receiving this exception when I don't think I'm chaining any methods together. Could you point me in the right direction as to what I'm doing wrong, or what I'm trying to do that you don't support?

I'm trying to setup a method that is marked as async Task<ApiResult<ApiResponse>> -- I have not seen any examples in your docs that support this behavior but this compiles just fine.

Help me understand what's going on here?

 public class TestClassMock : MockBase<ITestClass>, ITestClass
    {
        public TestClassMock(MockBehavior behavior = MockBehavior.Loose)
            : base(behavior)
        {
            if (behavior == MockBehavior.Loose)
            {
                var result = Task.FromResult(
                    new ApiResult<ApiResponse>
                        {
                            HttpStatusCode = HttpStatusCode.OK, 
                            Status = ApiCallStatus.Success, 
                            ResultData = new ApiResponse
                                             {
                                                 SomeArray = new[]
                                                                         {
                                                                             new PocoObject { SomeString = "12345abcdef" }
                                                                         }
                                             }
                        });

                this.When(x => this.RegisterAsync(It.IsAny<ApiRequest>(), It.IsAny<INetworkSettings>())) //Exception is thrown on this line
                    .Return(result); 
            }
        }

        public async Task<ApiResult<ApiResponse>> RegisterAsync(ApiRequest apiRequestData, INetworkSettings networkSettings = null)
        {
            return await this.Apply(x => x.RegisterAsync(apiRequestData, networkSettings));
        }
}

set-only properties

set-only properties are currently unsupported, for reasons explained in the documentation.

Think about possible alternatives and whether they're worth it.

Generated mock does not account for like-named members in different interfaces

public interface IFirst
{
    void Foo();
}

public interface ISecond
{
    void Foo();
}

public interface IAggregate : IFirst, ISecond
{
}

This will generate an invalid mock implementation of IAggregate because it will have two Foo methods. Not sure how best to address this. Obviously at least one implementation would need to be explicit, but which? Or perhaps the generator should recognise this situation and just skip the generation of Foo altogether, leaving it to the user to disambiguate...

PCLMockCodeGen.exe method generation bug.

Hi, developers!

I use PCLMockCodeGen.exe tool for generate mocks. When code was generated I found the next error in my Mocks.cs file:

public System.Double ToDisplayX(System.Double x)
{
    return this.Apply(x => x.ToDisplayX(x));
}

As you can see, PCLMockCodeGen tool generate param in anonymous method with "x" name, but my function argument already have "x" name. In this case Visual Studio shows error and this code can not be compiled.

Using Verify with Prism's NavigationService and NavigationParameter

I'm trying to verify that a navigation method on the NavigationService is called exactly once with the following code:

var navigationService = new NavigationServiceMock();
var viewModel = new CatalogPageViewModel(navigationService);

// Call
viewModel.CreateNewItemCommand.Execute(null);
var item = GetLatestCreatedItem();
var parameters = new NavigationParameters();
parameters.Add("id", item.Id);

// Verify
navigationService.Verify(x => x.NavigateAsync("EditPage", parameters)).WasCalledExactlyOnce();

However it yields the following exception:

PCLMock.VerificationException : Verification that NavigateAsync(It.Is("EditPage"), It.Is(?=id=89003df7-36a0-4319-8299-1195f3b7b5de [Prism.Navigation.NavigationParameters])) was called exactly once failed because it was called 0 times.
 at 
PCLMock.VerifyContinuation.ThrowVerificationException (System.String format, System.Object[] args) [0x00011] in
....

I've added breakpoints and the NavigateAsync sure is being hit with the exact same parameters, so I assume it fails because it expects the parameters to be an exact object and not another instance of the same class.

I would like to verify that a NavigationParameters is passed to the NavigateAsync and that the NavigationParameters should have a id key with the value of the Item.Id.

Is this possible?

Default exception message for WhenContinuation.Throw()

There is no message assigned to the exception thrown by the parameterless overload of WhenContinuation.Throw(). This results in an InvalidOperationException with no message, which can be confusing when debugging failing unit tests.

Add an appropriate error message. Perhaps "Mock has been configured to throw when accessing this member."

NullReferenceException when configuring expectation

When configuring expectations for Akavache's IBlobCache, I did something like this:

this
    .When(x => x.GetCreatedAt(It.IsAny<IEnumerable<string>>()))
    .Return(Observable.Return<Dictionary<string, DateTimeOffset?>>(null));

But this resulted in an exception:

System.NullReferenceException: Object reference not set to an instance of an object.
   at PCLMock.MockBase`1.GetContinuationKey(LambdaExpression selector)
   at PCLMock.MockBase`1.EnsureWhenContinuationCollection(LambdaExpression memberSelector)
   at PCLMock.MockBase`1.AddOrReplaceWhenContinuation(LambdaExpression memberSelector, WhenContinuation continuation)
   at PCLMock.MockBase`1.When[TMember](Expression`1 selector)

Library should be strongly signed

This would be beneficial for projects that are strongly signed and would like to utilize this library.

In case of projects for tests, they need to be signed when testing signed library with [InternalsVisibleTo] attribute set.

Configuration.FromXDocument cast bug

The Configuration.FromXDocument method includes a call to Cast. This can fail when comments are interspersed amongst the XML elements. OfType should be used instead.

Add verbose switch

Add a verbose/logging switch to the console generator so it's obvious what decisions it is making.

Console Code generation broken

When trying to use the console runner as a pre build event the resulting mocks.g.cs file can not resolve all types, as it omits the global:: keyword. Furthermore it also sometimes omits generic types in Tasks. When using the t4 template it works perfectly.

Try code-gen'ing with T4 and Roslyn

Attempt to write a T4 template that uses Roslyn to code-gen mock implementations. Would probably need to be driven by some kind of input file telling it which types to generate mocks for.

netstandard/netcore

V5 of PCLMock will (hopefully) be netstandard/netcore. This is a checklist of stuff I need to do/problems I need to solve for that to happen.

  • Source gen
    • Consider all symbols, not just those in the project in which generation is instigated (actually, pretty sure this is not possible with C# Source Generators, but trying to confirm. If not, remember to simplify the symbol enumeration logic so that it doesn't crawl all dependencies).
    • Forward diagnostics (errors/warnings) onto the compiler
    • Is there a sensible way I could make debugging easier by exposing the log under strict circumstances? No, not really :(
  • Reinstate console generator
    • Likely need generator to accept an enumeration of compilations from which to generate mocks. Console generator can pass in compilations from all solution projects.
    • Forward Buildalyzer logs on appropriately
  • Retire T4 generator?
  • Improve logging infrastructure and log messages
  • Modernize build scripts
    • Cake
    • NuGet packaging done via MSBuild
  • Update docs

All these notes are old, but just keeping them around in case I need to refer to them.

Here is a useful reference on creating a NuGet package for the console runner.

Another useful reference with respect to executing T4 templates in an SDK-style csproj.

UPDATE (24/05/18): had another crack at this using Buildalyzer and am giving up in frustration again. I was able to move the code base in the right direction (reinstating tests, for example), but ultimately wasn't able to progress with the actual problem. I need to record this because I'll otherwise forget. These are the problems I'm noticing:

  1. Types that are referenced by the target code don't resolve correctly unless they're core (already referenced) types. For example, if the target code uses NodaTime, all NodaTime types won't be qualified in the generated code.
  2. In attempting to address point 1, I figured it was because referenced assemblies weren't being loaded correctly into the Project instances. Indeed, that looks like it might be the case. On a hunch, I tried doing a dotnet restore against the target project before running the generator again, but this results in an exception (see below)
System.ArgumentException
  HResult=0x80070057
  Message=An item with the same key has already been added. Key: Microsoft.CodeAnalysis.CSharp.CSharpCompilationReference
  Source=System.Private.CoreLib
  StackTrace:
   at System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(Object key)
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.<FinalizeCompilationAsync>d__30.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.<BuildCompilationInfoFromScratchAsync>d__24.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.<GetOrBuildCompilationInfoAsync>d__22.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.<GetCompilationSlowAsync>d__19.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at PCLMock.CodeGeneration.Generator.<>c__DisplayClass3_0.<<GenerateMocksAsync>b__0>d.MoveNext() in C:\Users\kent\Repository\PCLMock\Src\PCLMock.CodeGeneration\Generator.cs:line 77

UPDATE (06/07/18): I've successfully reproduced the above problem and submitted a bug report here.

NullReferenceException thrown when `Do` method is setup using async/await

Normally in Moq, when I want to validate that a method was called with a complex object that has a certain property matched, I would do something like:

object.Verify(x => x.Method(It.Is(x => x.Property == "someValueIExpect")), Times.Once)

In this library, it seems like the only way to achieve this type of behavior is with the .Do() method and setting a local boolean there. However, when I try to do this in a method that uses async/await, I get a NullReferenceException thrown.

Consider the example library code:

    public interface ITestClass
    {
        Task<ApiResult<ApiResponse>> RegisterAsync(ApiRequest apiRequestData);

        ApiResult<ApiResponse> Register(ApiRequest apiRequestData);
    }

    public class ApiRequest
    {
        public Guid Id { get; set; }
    }

    public class ApiResponse
    {
        public PocoObject[] SomeArray { get; set; }
    }

    public class PocoObject
    {
        public string SomeString { get; set; }
    }

    public class ApiResult<TResponseType>
    {

        public HttpStatusCode HttpStatusCode { get; set; }

        public ApiCallStatus Status { get; set; }

        public TResponseType ResultData { get; set; }

    }

    public enum ApiCallStatus
    {
        Success,
        Failure
    }

And the following Mock and XUnit Tests:

    public class TestClassMock : MockBase<ITestClass>, ITestClass
    {
        public TestClassMock(MockBehavior behavior = MockBehavior.Loose)
            : base(behavior)
        {
        }

        public async Task<ApiResult<ApiResponse>> RegisterAsync(ApiRequest apiRequestData)
        {
            return await this.Apply(x => x.RegisterAsync(apiRequestData)); //Null Reference Exception thrown here in the first test
        }

        public ApiResult<ApiResponse> Register(ApiRequest apiRequestData)
        {
            return this.Apply(x => x.Register(apiRequestData));
        }
    }


public class UnitTests
    {
        [Fact]
        public async Task TestRegisterAsync() //Fails :(
        {
            var mock = new TestClassMock();
            var id = Guid.NewGuid();
            var calledWithId = false;

            mock.When(x => x.RegisterAsync(It.IsAny<ApiRequest>())).Do((ApiRequest req) => calledWithId = req.Id == id);

            var result = await mock.RegisterAsync(new ApiRequest { Id = id });

            mock.Verify(x => x.RegisterAsync(It.IsAny<ApiRequest>()));
            Assert.True(calledWithId);
        }

        [Fact]
        public async Task TestRegisterAsync_WithoutTest() //Success!
        {
            var mock = new TestClassMock();
            var id = Guid.NewGuid();

            mock.When(x => x.RegisterAsync(It.IsAny<ApiRequest>())).Return(
                Task.FromResult(new ApiResult<ApiResponse>
                                        {
                                            HttpStatusCode = HttpStatusCode.OK,
                                            ResultData = new ApiResponse
                                                            {
                                                                SomeArray = new[]
                                                                                {
                                                                                    new PocoObject() { SomeString = "ABC123" } 
                                                                                }
                                                            }
                                        }));

            var result = await mock.RegisterAsync(new ApiRequest { Id = id });

            mock.Verify(x => x.RegisterAsync(It.IsAny<ApiRequest>()));
            Assert.Equal("ABC123", result.ResultData.SomeArray.First().SomeString);
        }

        [Fact]
        public async Task TestRegister() //Success!
        {
            var mock = new TestClassMock();
            var id = Guid.NewGuid();
            var calledWithId = false;

            mock.When(x => x.Register(It.IsAny<ApiRequest>()))
                .Do((ApiRequest req) => calledWithId = req.Id == id);

            mock.Register(new ApiRequest { Id = id });

            mock.Verify(x => x.Register(It.IsAny<ApiRequest>()));
            Assert.True(calledWithId);
        }
    }

When I run this in Xamarin.iOS test runner, The first test that has a .Do() (async/await) fails while second test without a .Do() (async) is successful, and the third test with a .Do() is also successful.

It seems that there is a bug with async/await and registering a .Do() in that this null reference exception is thrown.

screen shot 2015-09-10 at 5 11 59 pm

I created a minimal reproduction of the issue here, requires Xamarin (tested on visual studio): http://cl.ly/2T2P3u3n361t

Non-static method requires a target

A verification along the lines of:

mock
    .Verify(x => x.SomeCall(It.Matches(y => y.SomeNullableThing.HasValue)))
    .WasCalledExactlyOnce();

results in an exception:

System.Reflection.TargetException: Non-static method requires a target

A simple workaround in this specific example is to change to:

mock
    .Verify(x => x.SomeCall(It.Matches(y => y.SomeNullableThing != null)))
    .WasCalledExactlyOnce();

NOTE: tested on mono only (Xamarin/iOS).

VB code generation broken

It seems the WithStatements method in VB's syntax generator does not work correctly. No statements are being added to the method.

Mocking Events

Events are not currently mocked for reasons explained in the documentation.

Consider ways in which this might be supported, and whether it's worth it. Also think about whether a half-way approach is a Good Idea.

Different behavior under mono

It seems that property expressions are somewhat different running under mono so are causing issues for the visitors. Example:

mock
    .When(x => x.SomeProperty)
    .Return(1);

This is currently failing because the visitor is unable to extract the requisite information from the expression.

Issues with mocking a method to throw an exception

Hi,

I found two annoying issues when mocking a method to throw an exception:

  1. When doing the following, the exception is thrown but "called" will stay false:
    bool called = false;
    mock.When(x => x.SomeMethod()).Do(() => called = true).Throw()
    try { mock.SomeMethod(); }
    catch { }
  2. When throwing an exception in the Do action, it will be wrapped under a TargetInvocationException:
    mock.When(x => x.SomeMethod()).Do(() => throw new MyException())
    try { mock.SomeMethod(); }
    catch (MyException) { /* Will never go there. */ }
    catch (TargetInvocationException) { /* Will go there instead. */ }

Thanks for all the nice work!

PCLMockCodeGen.exe interface with event generation bug.

Hi, developers!

I use PCLMockCodeGen.exe tool for generate mocks. When code was generated I found that tool not generated code for event in my interface:

public interface IProductLicenseService
{
   event LicenseChangedEventHandler LicenseChanged;
}

Improve verification failure messages

The failure messages reported when verifications are not met can result in confusion because they do not always contain sufficient information. Examples of good failure messages are:

  • Verification that SomeMethod() was not called failed because it was called 1 time.
  • Verification that SomeMethod() was called exactly once failed because it was called 2 times.
  • Verification that SomeMethod() was called exactly 2 times failed because it was called 1 time.
  • Verification that SomeMethod(It.Is("abc")) was called exactly once failed because it was called 1 time.
  • Verification that SomeMethod(It.IsAny()) was called exactly once failed because it was called 1 time.

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.