How to mock an interface returned as property from another mock? - c#

I have the following interfaces:
interface IManufacturing
{
IJobApi JobApi {get;}
}
interface IJobApi
{
IList<JobSpec> GetSpecs (string wo, string name);
}
I have a class which uses IManufacturing and calls GetSpecs() like so:
var specs = _manufacturing.JobApi.GetSpecs (wo, name);
I setup my mocks like:
var jobApi = A.Fake<IJobApi> ();
A.CallTo (() => jobApi.GetSpecs (It.IsAny<string> (), It.IsAny<string> ()))
.Invokes (() => System.Diagnostics.Trace.WriteLine("GetSpecs called!"))
.Returns (new List<JobSpec>
{
new JobSpec("blablabla", "0.125", "something")
});
var manufacturing = A.Fake<IManufacturing> ();
A.CallTo (() => manufacturing.JobAPI)
.Invokes (() => System.Diagnostics.Trace.WriteLine ("JobAPI called!"))
.Returns (jobApi);
Upon running the test, I only see the "JobAPI called" string in the output.
So, the GetSpecs() does not get mocked and indeed the caller throws because it expected a list of specs whereas it received an empty string...
What could be the culprit here?
Thanks.

Dammit!
You're gonna laugh, I have!
Turned out that the following line
A.CallTo (() => jobApi.GetSpecs (It.IsAny<string> (), It.IsAny<string> ()))
was not correct for FakeItEasy. It should be written as
A.CallTo (() => jobApi.GetSpecs (A<string>.Ignored, A<string>.Ignored))
So, you may wonder why it did compile and run... Yeah me too. ;)
It.IsAny is for Moq (!)
I had a Using Moq lingering at the top of the class. (I'm in the process of switching to fakeiteasy from moq).
[face palm]
TGIF

Related

Unit testing ViewModel property bound to ReactiveCommand IsExecuting

I'm new to ReactiveUI and am following the example set out here, and unit testing as I go.
As expected, the sample code works perfectly, but my unit test which asserts that the SpinnerVisibility property changes as expected when the IsExecuting property of my ReactiveCommand changes, does not.
As per the sample, I have properties on my view model for a spinner visibility and a command to execute a search:
public Visibility SpinnerVisibility => _spinnerVisibility.Value;
public ReactiveCommand<string, List<FlickrPhoto>> ExecuteSearch { get; protected set; }
And in the view model constructor I set up the ExecuteSearch command and SpinnerVisibility is set to change when the command is executing:
public AppViewModel(IGetPhotos photosProvider)
{
ExecuteSearch = ReactiveCommand.CreateFromTask<string, List<FlickrPhoto>>(photosProvider.FromFlickr);
this.WhenAnyValue(search => search.SearchTerm)
.Throttle(TimeSpan.FromMilliseconds(800), RxApp.MainThreadScheduler)
.Select(searchTerm => searchTerm?.Trim())
.DistinctUntilChanged()
.Where(searchTerm => !string.IsNullOrWhiteSpace(searchTerm))
.InvokeCommand(ExecuteSearch);
_spinnerVisibility = ExecuteSearch.IsExecuting
.Select(state => state ? Visibility.Visible : Visibility.Collapsed)
.ToProperty(this, model => model.SpinnerVisibility, Visibility.Hidden);
}
My initial attempt was to directly invoke the command:
[Test]
public void SpinnerVisibility_ShouldChangeWhenCommandIsExecuting()
{
var photosProvider = A.Fake<IGetPhotos>();
var fixture = new AppViewModel(photosProvider);
fixture.ExecuteSearch.Execute().Subscribe(_ =>
{
fixture.SpinnerVisibility.Should().Be(Visibility.Visible);
});
fixture.SpinnerVisibility.Should().Be(Visibility.Collapsed);
}
This did result in the state => state ? Visibility.Visible : Visibility.Collapsed lambda being executed, but the subsequent assertion fails as for some reason SpinnerVisibility is still Collapsed.
My next attempt was to indirectly invoke the command by emulating a search using TestScheduler:
[Test]
public void SpinnerVisibility_ShouldChangeWhenCommandIsExecuting()
{
new TestScheduler().With(scheduler =>
{
var photosProvider = A.Fake<IGetPhotos>();
var fixture = new AppViewModel(photosProvider);
A.CallTo(() => photosProvider.FromFlickr(A<string>.Ignored)).ReturnsLazily(
() => new List<FlickrPhoto> { new FlickrPhoto { Description = "a thing", Title = "Thing", Url = "https://thing.com" } });
fixture.SearchTerm = "foo";
scheduler.AdvanceByMs(801); // search is throttled by 800ms
fixture.SpinnerVisibility.Should().Be(Visibility.Visible);
});
}
As before, the lambda executes, state is true but then instantly re-executes, with state back to false, presumably because, being mocked, photosProvider.FromFlickr would return instantly (unlike retrieving images from the API normally), which would then mean the command was no longer executing.
I then came across Paul Bett's response to a similar question, and added an Observable.Interval to my mock:
A.CallTo(() => photosProvider.FromFlickr(A<string>.Ignored)).ReturnsLazily(
() =>
{
Observable.Interval(TimeSpan.FromMilliseconds(500), scheduler);
return new List<FlickrPhoto> {new FlickrPhoto {Description = "a thing", Title = "Thing", Url = "https://thing.com"}};
});
and the corresponding test changes:
scheduler.AdvanceByMs(501);
fixture.SpinnerVisibility.Should().Be(Visibility.Collapsed);
This had no effect.
Finally, I awaited the Interval:
A.CallTo(() => photosProvider.FromFlickr(A<string>.Ignored)).ReturnsLazily(async
() =>
{
await Observable.Interval(TimeSpan.FromMilliseconds(500), scheduler);
return new List<FlickrPhoto> {new FlickrPhoto {Description = "a thing", Title = "Thing", Url = "https://thing.com"}};
});
This allowed the fixture.SpinnerVisibility.Should().Be(Visibility.Visible) assertion to pass, but now regardless how far I advance the scheduler, the mocked method never seems to return and so the subsequent assertion fails.
Is this approach using TestScheduler correct/advised? If so, what am I missing? If not, how should this type of behaviour be tested?
First off, you are trying to test two independent things in one test. Separating the logic into more focused tests will cause you fewer headaches in the future when refactoring. Consider the following instead:
SearchTerm_InvokesExecuteSearchAfterThrottle
SpinnerVisibility_VisibleWhenExecuteSearchIsExecuting
Now you have unit tests that are verifying each piece of functionality individually. If one fails, you'll know exactly which expectation is broken because there is only one. Now, onto the actual tests...
Based on your code, I assume you're using NUnit, FakeItEasy, and Microsoft.Reactive.Testing. The recommended strategy for testing observables is to use the TestScheduler and assert the final outcome of the observable.
Here is how I would implement them:
using FakeItEasy;
using Microsoft.Reactive.Testing;
using NUnit.Framework;
using ReactiveUI;
using ReactiveUI.Testing;
using System;
using System.Reactive.Concurrency;
...
public sealed class AppViewModelTest : ReactiveTest
{
[Test]
public void SearchTerm_InvokesExecuteSearchAfterThrottle()
{
new TestScheduler().With(scheduler =>
{
var sut = new AppViewModel(A.Dummy<IGetPhotos>());
scheduler.Schedule(() => sut.SearchTerm = "A");
scheduler.Schedule(TimeSpan.FromTicks(200), () => sut.SearchTerm += "B");
scheduler.Schedule(TimeSpan.FromTicks(300), () => sut.SearchTerm += "C");
scheduler.Schedule(TimeSpan.FromTicks(400), () => sut.SearchTerm += "D");
var results = scheduler.Start(
() => sut.ExecuteSearch.IsExecuting,
0, 100, TimeSpan.FromMilliseconds(800).Ticks + 402);
results.Messages.AssertEqual(
OnNext(100, false),
OnNext(TimeSpan.FromMilliseconds(800).Ticks + 401, true)
);
});
}
[Test]
public void SpinnerVisibility_VisibleWhenExecuteSearchIsExecuting()
{
new TestScheduler().With(scheduler =>
{
var sut = new AppViewModel(A.Dummy<IGetPhotos>());
scheduler.Schedule(TimeSpan.FromTicks(300),
() => sut.ExecuteSearch.Execute().Subscribe());
var results = scheduler.Start(
() => sut.WhenAnyValue(x => x.SpinnerVisibility));
results.Messages.AssertEqual(
OnNext(200, Visibility.Collapsed),
OnNext(301, Visibility.Visible),
OnNext(303, Visibility.Collapsed));
});
}
}
Notice there is no need to even fake/mock IGetPhotos because your tests aren't verifying anything based on the duration of the command. They just care about when it executes.
Some things can be difficult to wrap your head around at first, such as when a tick actually occurs, but it's very powerful once you get the hang of it. Some debate could be had about the usage of ReactiveUI in the tests (e.g. IsExecuting, WhenAnyValue), but I think it keeps things succinct. Plus, you're using ReactiveUI in your application anyway so if those things broke your test I'd consider that a good thing.

How to chain constructors in Structuremap?

Is there a way to chain the constructors in Structuremap? I would want a more succinct code - basically trying to get rid of the new keyword in codebase.
Currently what I have:
container.Configure(c =>
{
c.For<IDataContext>()
.Singleton()
.Use(new CarDataContextWrapper(new CarDataContext(Settings.Default.ConnectionString)
{
CommandTimeout = 60
}));
});
To inject in the constructor parameters, I would want to using .Ctor declaration. But how would I do it for the second class that I want to initialize?
container.Configure(c =>
{
c.For<IDataContext>()
.Use<CarDataContextWrapper>()
.Ctor<CarDataContext>().Is(x=>); // HOW TO SET THIS?
});
container.Configure(c =>
{
c.For<IDataContext>()
.Use<CarDataContextWrapper>("getting context", ctx=>
{
return ctx.GetInstance<CarDataContextWrapper>();
});
// Also need to tell SM how to build CarDataContextWrapper
});

RhinoMocks mock method without return

I am new to mocking. I need to mock method (it doesn't have return value). I cannot find any examples of how to mock a method. I need to mock ITempDa.Import method.
var stub = MockRepository.GenerateStub<ITempDA>();
stub.Stub(x => x.Import(param1)). ???
public void MockedImport() {
// some processing here
}
ITempDa.Import should be mocked and instead some internal method "MockedImport" should be called.
As #JamesLucas said you don't need to use Return() method(you should use this method only when your method is not void).
In this case you should use the Do() method:
var stub = MockRepository.GenerateStub<ITempDA>();
stub.Stub(x => x.Import(Arg<object>.Is.Anything))
.Do(new Action<object>(o => MockedImport()));
or if MockedImport ths same arguments as Import:
stub.Stub(x => x.Import(Arg<object>.Is.Anything))
.Do(new Action<object>(MockedImport);
You should use WhenCalled method when the method under test called your fake and you want to intercept the execution(execute something + change return value/change arguments/do additional steps and etc...). Another reason to use Do instead of WhenCalled is, your code become more readable.
Usually I do not recommend to use IgnoreArguments method. The reason is quite simple, you test the method behaviour. When something violate the method behaviour then the test should fail. IgnoreArguments easily hide things. However, if the calling parameters aren't important do:
stub.Stub(x => x.Import(null))
.IgnoreArguments()
.Do(new Action<object>(o => MockedImport()));
In this instance you don't need a Return() call as the method is void returning. If you want to intercept the call and perform some logic on the mocked operation then use WhenCalled. In this scenario it's also worht just ignoring the arguments in the Stub and handling everything in the WhenCalled expression. e.g.
var stub = MockRepository.GenerateStub<ITempDA>();
stub.Stub(x => x.Import(null))
.IgnoreArguments()
.WhenCalled(invocation =>
{
var arg = invocation.Arguments[0] as ...;
// etc
});

Moq: Setup a mocked method to fail on the first call, succeed on the second

What's the most succinct way to use Moq to mock a method that will throw an exception the first time it is called, then succeed the second time it is called?
I would make use of Callback and increment a counter to determine whether or not to throw an exception from Callback.
[Test]
public void TestMe()
{
var count = 0;
var mock = new Mock<IMyClass>();
mock.Setup(a => a.MyMethod()).Callback(() =>
{
count++;
if(count == 1)
throw new ApplicationException();
});
Assert.Throws(typeof(ApplicationException), () => mock.Object.MyMethod());
Assert.DoesNotThrow(() => mock.Object.MyMethod());
}
public interface IMyClass
{
void MyMethod();
}
Starting with Moq 4.2 you can just use the built-in method SetupSequence() (as stated by #RichardBarnett comment).
Example:
var mock = new Mock<IMyClass>();
mock.SetupSequence(x => x.MyMethod("param1"))
.Throws<MyException>()
.Returns("test return");
The best that I've come up with so far is this:
interface IFoo
{
void Bar();
}
[Test]
public void TestBarExceptionThenSuccess()
{
var repository = new MockRepository(MockBehavior.Default);
var mock = repository.Create<IFoo>();
mock.Setup(m => m.Bar()).
Callback(() => mock.Setup(m => m.Bar())). // Setup() replaces the initial one
Throws<Exception>(); // throw an exception the first time
...
}
Phil Haack has an interesting blog post on setting up a method to return a particular sequence of results. It seems that it would be a good starting point, with some work involved, because instead of a sequence of values of a certain type, you would need now to have a sequence of results which could be of type T, or an exception.

Moq verify method fails even though method will be called

I have some troubles using Moq. Following unit test throws an exception, even though the according method will be called.
[TestMethod]
public void CreateFinishTest() {
// mock methods
factoryMock.Setup(f => f.LoadPlan("TestPlanDoNotUse")).Returns(testPlan).Verifiable();
factoryMock.Setup(f => f.CreateFinish(It.IsAny<CreateFinishMessage>(), It.IsAny<string>())).Returns(testFinish.Id).Verifiable();
try {
var cfm = new CreateFinishMessage() {
ClientId = 11,
MessageId = 23456,
CustomerId = 6,
FinishName = "MyFinish",
PlanId = "TestPlanDoNotUse"
};
var cmd = sysCfg.Executor.CreateFinish(cfm); // calls LoadPlan with cfm.PlanId and CreateFinish with cfm and cfm.PlanId
sysCfg.Executor.Execute(cmd);
factoryMock.Verify(f => f.LoadPlan("TestPlanDoNotUse"), Times.Exactly(1));
factoryMock.Verify(f => f.CreateFinish(It.IsAny<CreateFinishMessage>(), It.IsAny<string>()), Times.Exactly(1));
} catch (Exception exc) {
Assert.Fail(exc.Message);
}
}
This Error occurs:
Expected invocation on the mock exactly 1 times, but was 0 times: f => f.LoadPlan("TestPlanDoNotUse")
Configured setups:
f => f.LoadPlan("TestPlanDoNotUse"), Times.Once
Performed invocations:
IFactory.LoadPlan("TestPlanDoNotUse")
Factory.CreateFinish(IndiValue.LiveMarket.IndiCore.Communication.MessagingFormat.CreateFinishMessage, "MyFinish")
I've tried several different Verify-Calls but it won't work. And the Error which occurs seems quite confusing it's says that LoadPlan("TestPlanDoNotUse") is never called, but it's listed # Performed invocations.
Problem solved:
I think i found the problem, it wasn't a Moq problem. In sysCfg.Executor.CreateFinish(cfm) a new thread was created and started. This thread wasn't finished and so factoryMock.Verify(...) failed.
I used AutoResetEvents:
// create AutoResetEvent triggers
AutoResetEvent m_testTrigger1 = new AutoResetEvent(false);
// mock methods
factoryMock.Setup(f => f.LoadPlan(It.IsAny<string>())).Returns(testPlan).Callback(() => m_testTrigger1.Set());
// do something
// wait for triggers
bool didReturn1 = m_testTrigger1.WaitOne(timeOut);
On the Verifiable not being called, it's important that the arguments in your expectation match the arguments that are being used by the production code.
Regarding the use of Thread.Sleep, avoid it wherever possible as it will only slow down the tests to meet your slowest machine. I typically introduce WaitHandles into my tests to ensure that the tests run as fast as the code.
Take a peek here on a small utility that uses WaitHandles with events.
You do not usually use Verifiable() in your setups in conjuction with the Verify(expr, times) methods. Does it work if you remove the .Verifiable() calls?
I guess this is a me-too answer, but I believe this to be a simpler solution than many of the mentioned before.
I implemented a WaitFor function which utilizes a lambda callback to evaluate a condition:
public static void WaitFor(Func<bool> action, long timeoutMillis = 10000)
{
Stopwatch elapsed = Stopwatch.StartNew();
elapsed.Start();
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
while (!action())
{
if (elapsed.ElapsedMilliseconds > timeoutMillis)
{
throw new TimeoutException("Timed out waiting for condition to become true after " + elapsed.ElapsedMilliseconds + " ms");
}
Thread.Sleep(0);
}
}
and the test code looks like this:
[Test]
public void ShouldNackUnparsableInboundMessage()
{
var nackCalled = false;
_mock.Setup(m => m.BasicNack(999, false, false)).Callback(() =>
{
nackCalled = true;
});
... do whatever which invokes the call on another thread.
WaitFor(() => nackCalled);
// Test will fail with timeout if BasicNack is never called.
}

Categories

Resources