[Subject(typeof(OnceADayProcessor))]
public class When_processing_process_twice
{
private static ICanBeProcessedOnceADay ProcessedOnceADay;
private Establish context = () => { OnceADayProcessor.Now = () => new DateTime(2011, 1, 1, 0, 0, 0, 0); };
private Because of = () =>
{
ProcessedOnceADay = MockRepository.GenerateMock<ICanBeProcessedOnceADay>();
ProcessedOnceADay.Process();
ProcessedOnceADay.Process();
};
private It should_execute = () => ProcessedOnceADay.AssertWasCalled(x => x.Expect(p => p.Process()));
private It should_execute_only_once = () => ProcessedOnceADay.AssertWasNotCalled(x => x.Expect(p => p.Process()));
}
edited solution:
[Subject(typeof(OnceADayProcessor))]
public class When_processing_a_process_twice_at_the_same_day
{
static ICanBeProcessedOnceADay canBeProcessedOnceADay;
Establish context = () =>
{
canBeProcessedOnceADay = A.Fake<ICanBeProcessedOnceADay>();
};
Because of = () =>
{
OnceADayProcessor.Process(canBeProcessedOnceADay);
OnceADayProcessor.Process(canBeProcessedOnceADay);
};
It should_execute_only_once = () =>
A.CallTo(() => canBeProcessedOnceADay.Process()).MustHaveHappened(Repeated.Exactly.Once);
}
var mock = MockRepository.GenerateMock<ICanBeProcessedOnceADay>();
mock.Expect(a => a.Process()).Repeat.Times(1);
...
mock.VerifyAllExpectations();
I would replace the calls to stub.Expect() and stub.VerifyAllExpectations() with stub.AssertWasCalled(x => x.Process(), o => o.Repeat.Once()) in the It. If you have more than one expectation against the stub you can then put each assertion in one It and have them fail (or succeed) independently of each other.
The creation of the stub would go into Establish (essentially, creation of any dependencies and the System Under Test is part of the "arrange" phase in unit testing).
Also consider not to use GenerateMock but GenerateStub as mocks will likely lead to brittle tests when you call other methods than the ones specified with Expect. Libraries like FakeItEasy generally provide better and more discoverable APIs, are easier to learn and will make you fall into the "pit of success".
If you want to ensure that a method is called only once, you need a strict mock:
var mock = MockRepository.GenerateStrictMock<IShouldOnlyBeCalledOnce>();
mock.Expect(a => a.Process()).Repeat.Once();
sut.Process(mock)
mock.VerifyAllExpectations();
If you just use GenerateMock, it will perform an "at least" check. This also goes for Repeats.Times(x) too.
Related
I have a service that
Makes a call to each registered class that implements a specific interface (IUnorderedService)
Then makes a final call to another service (IFinalService)
I want to write a test that asserts that my service makes a call to each IUnorderedService in no specific order, and then makes a call to the IFinalService. Using FakeItEasy, is there any way to do this?
My implementation looks like this (much simplified):
public class MyService
{
private readonly IFinalService finalService;
private readonly IEnumerable<IUnorderedService> unorderedServices;
public MyService(
IFinalService finalService,
IEnumerable<IUnorderedService> unorderedServices)
{
this.finalService = finalService;
this.unorderedServices = unorderedServices;
}
public void Execute()
{
foreach (var unorderedService in this.unorderedServices)
{
unorderedService.Execute();
}
this.finalService.Execute();
}
}
And my test method would look something like this
public void ShouldCallUnorderedService_BeforeCallingFinalService()
{
// Arrange
...
// Act
myService.Execute();
// Assert
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly();
}
// Should be asserted that this call occurs after all of the above calls have occurred.
A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly();
}
I have played around with the A.CallTo().Then() syntax which works great for most purposes, but I don't see a way assert occurrence of multiple unordered calls prior to an ordered call.
There's nothing directly built into FakeItEasy for this scenario. One option would be to intercept the calls as they are made. Then you could verify the order was as you wanted. The call-intercepting feature is (I believe) infrequently used, so this might be less understandable, but could be worth pursuing.
Then I thought about leveraging the "callback" or Invokes facility on a Fake to record whether a fake call was supposed to be final or not, then verify the setting at the end of the test:
[Fact]
public void ShouldCallUnorderedService_BeforeCallingFinalService()
{
var lastKindOfService = "none";
var unorderedServices = new [] {
A.Fake<IUnorderedService>(),
A.Fake<IUnorderedService>(),
A.Fake<IUnorderedService>(),
};
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).Invokes(() => lastKindOfService = "unordered");
}
var finalService = A.Fake<IFinalService>();
A.CallTo(() => finalService.Execute()).Invokes(() => lastKindOfService = "final");
var service = new MyService(finalService, unorderedServices);
service.Execute();
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly();
}
A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly();
lastKindOfService.Should().Be("final");
}
Of course this could be prettied up with a helper method or enums for the state. And if there's any asynchrony, you might want to serialize the updates.
You can put the A.CallTo().Then() into your foreach
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly()
.Then(A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly()
}
So you are checking that each call to the unordered service happened before the call to the final service. Unfortunately this is not a bulk check, but I think the end result will still prove code correctness
I'm newbie working with Rhino Mock and I'm getting this error that I cannot understand why. Here the test
public void TestGet()
{
var installationReference = new Guid("21D7D135-6E9E-4F92-8313-873CA3ABDCD8");
var study = MockRepository.GenerateMock<IStudy>();
var installation = MockRepository.GenerateMock<IInstallation>();
var license = MockRepository.GenerateMock<ILicense>();
var participant = MockRepository.GenerateMock<IStudyParticipant>();
var clinicalPartner = MockRepository.GenerateMock<IClinicalPartner>();
clinicalPartner.Stub(c => c.FirstName).Return("John");
clinicalPartner.Stub(c => c.LastName).Return("Doe");
installation.Stub(i => i.Reference).Return(installationReference);
license.Stub(l => l.Installations).Return(new List<IInstallation> { installation });
participant.Stub(p => p.Licenses).Return(new List<ILicense> { license });
participant.Stub(p => p.ClinicalPartner).Return(clinicalPartner);
participant.Stub(p => p.ClinicalPartnerStatus).Return(ClinicalPartnerStatus.Active);
study.Stub(s => s.Description).Return("Test WebAPI");
study.Stub(s => s.Participants).Return(new List<IStudyParticipant> { participant });
repository.Stub(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study));
repository.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference)))).Return(new DummyResult<IStudy>(study)).Repeat.Once();
repository.VerifyAllExpectations();
}
My GetStudiesByInstallationReference.cs
public class GetStudiesByInstallationReference : IQuery<IStudy>
{
public Guid InstallationReference { get; set; }
public GetStudiesByInstallationReference(Guid installationReference)
{
InstallationReference = installationReference;
}
public IQueryResult<IStudy> Execute(ISession session)
{
var criteria = session.CreateCriteria<IStudy>();
criteria.CreateAlias("participants", "p");
criteria.CreateAlias("p.licenses", "l");
criteria.CreateAlias("l.installations", "i");
criteria.Add(Restrictions.Eq("i.Reference", InstallationReference));
criteria.Add(Restrictions.Eq("Status", StudyStatus.Approved));
criteria.Add(Restrictions.Eq("p.ClinicalPartnerStatus", ClinicalPartnerStatus.Active));
criteria.Add(Restrictions.Le("StartDate", DateTime.Now));
criteria.Add(Restrictions.Or(
Restrictions.IsNull("EndDate"),
Restrictions.Gt("EndDate", DateTime.Now)));
return new CriteriaResult<IStudy>(criteria);
}
}
I want to test GetStudiesByInstallationReference was called one time.
What am I doing wrong?...it should pass the test as the Expect clause is the same used in the Stub but I still got the exception
Expected #1, Actual #0.
Anybody could help me with this?
Thanks in advance
I want to test GetStudiesByInstallationReference was called one time.
GetStudiesByInstallationReference is a type, and not a method that you expect to be called.
repository
.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study)).Repeat.Once();
This line from your code is setting up an expectation on the repository mock. It expects that the Query() method is called with a parameter of type GetStudiesByInstallationReference that has the correct installation reference GUID as a property. If this method isn't called with the correct parameter, you will get the error you describe when calling repository.VerifyAllExpectations().
It looks like your test is missing the actual call to the SUT i.e. the "Act" in Arrange/Act/Assert. Simply put, you need to execute some code that will cause the method on your repository to be called as you expect (or change the test).
I'm new to ReactiveUI. I have the following simple setup: a path to a csv can be specified and the containing datapoints will be displayed to the user (using oxyplot).
Now I'm trying to test the following subscription:
public GraphViewModel(IScreen hostScreen)
{
HostScreen = hostScreen;
setupGraphFormatting();
// Data Loading if path is valid
this.WhenAnyValue(viewModel => viewModel.PathToDataCsv)
.ObserveOn(RxApp.MainThreadScheduler)
.Throttle(TimeSpan.FromMilliseconds(500), RxApp.TaskpoolScheduler)
.Select(csvPath => csvPath?.Trim('"'))
.Where(csvPath => !string.IsNullOrEmpty(csvPath) && File.Exists(csvPath))
.Subscribe(csvPath =>
{
csvPath = csvPath?.Trim('"');
updatePlotModel(csvPath);
}, exception => {});
/* additional Code*/
}
And that's the corresponding UnitTest:
[Test]
public void If_PathToDataCsv_has_a_valid_value()
{
new TestScheduler().With(scheduler =>
{
string pathToValidCsvFile = "data.log";
var viewModel = new GraphViewModel(null);
scheduler.AdvanceByMs(1000);
viewModel.PathToDataCsv = pathToValidCsvFile;
scheduler.AdvanceByMs(1000);
viewModel.PlotModel.Series.Count.Should().Be(6);
});
}
My first implementation of WhenAnyValue didn't set any of the Schedulers specifically ( in Throttle and lacking any ObserverOn ):
public GraphViewModel(IScreen hostScreen)
{
HostScreen = hostScreen;
setupGraphFormatting();
// Data Loading if path is valid
this.WhenAnyValue(viewModel => viewModel.PathToDataCsv)
.Throttle(TimeSpan.FromMilliseconds(500))
.Select(csvPath => csvPath?.Trim('"'))
.Where(csvPath => !string.IsNullOrEmpty(csvPath) && File.Exists(csvPath))
.Subscribe(csvPath =>
{
csvPath = csvPath?.Trim('"');
updatePlotModel(csvPath);
}, exception => {});
/* additional Code*/
}
But then my Unittest failed. My assumption was that TestScheduler was being used for Throttle behind the scenes and I didn't have to do anything. Am I doing something wrong or is this the right way: If I want to use TestScheduler/TimeTravelâ„¢ I have to specify the schedulers the way I did?
Edit in response to Glenn Watsons answer:
Ok, now it's clear: The methods in question (Throttle, ObserverOn) of course do not use ReactiveUI's Schedulers, because these are methods from the Reactive Extensions Framework. So they can't be replaced implicitly by ReactiveUI in case of a UnitTest except I tell the methods to use the RxApp Schedulers...
RxApp provides the ThreadPoolScheduler when you are in release mode, and the testing scheduler when you are in unit test mode.
By default the reactive extensions (separate to ReactiveUI) will use their own default schedulers which are unaware of unit tests.
I have a ICreateService class that has dependency on ITicketApiAdapter. I've tried registering a mock ITicketAdaper so that it gets injected when I create an anonymous create service.
So, in setup, I have this register for the ticket adapter:
Fixture.Register(() =>
{
var ticketApiAdapter = new Mock<ITicketApiAdapter>();
ticketApiAdapter
.Setup( x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()))
.Returns(new SaveResult
{
Success = true,
Id = Fixture.CreateAnonymous<Guid>().ToString()
});
return ticketApiAdapter;
});
Fixture.Register(() => new CreateService(Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>().Object));
From my understanding, that should "freeze" both the ICreateService and Mock<ITicketApiAdapter> so that when I request an anonymous instance, it's the one I registered.
I have a test that looks like this:
[TestMethod]
public void CreateServiceCallsAddTicketComment()
{
var apiTicketAdapter = Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>();
var createTicketRequest = Fixture.CreateAnonymous<CreateTicketComment>();
var createService = Fixture.CreateAnonymous<CreateService>();
var results = createService.CreateTicketComment(createTicketRequest);
apiTicketAdapter
.Verify(x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()),
Times.Once());
Assert.IsTrue(results.All(x => x.Success));
Assert.IsTrue(results.All(x => x.Errors.Count == 0));
}
I expect the apiTicketAdapter to be the one I registered so that I can verify the method is called. If I step through, the TicketApiAdapter is called, but Moq says it wasn't.
Edit
This is the error I get:
CreateServiceCallsAddTicketComment threw exception:
Moq.MockException: Expected invocation on the mock once, but was 0
times: x => x.AddTicketComment(It.IsAny(), It.IsAny(),
It.IsAny())
Configured setups: x => x.AddTicketComment(It.IsAny(),
It.IsAny(), It.IsAny()), Times.Never No
invocations performed.
When you Register a code block, that code block is going to be invoked every time the Fixture instance resolves the requested type. This means that it's not frozen. If you want to Freeze something, one of the Freeze overloads are often easier to use.
Better yet, since you seem to be using Moq, may I suggest using the AutoMoq extension?
That would enable you to rewrite the test to something like this:
[TestMethod]
public void CreateServiceCallsAddTicketComment(new AutoMoqCustomization());
{
var fixture = new Fixture().Customize()
var apiTicketAdapter = fixture.Freeze<Mock<ITicketApiAdapter>>();
ticketApiAdapter
.Setup( x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()))
.Returns(new SaveResult
{
Success = true,
Id = Fixture.CreateAnonymous<Guid>().ToString()
});
var createTicketRequest = fixture.Freeze<CreateTicketComment>();
var createService = fixture.CreateAnonymous<CreateService>();
var results = createService.CreateTicketComment(createTicketRequest);
apiTicketAdapter
.Verify(x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()),
Times.Once());
Assert.IsTrue(results.All(x => x.Success));
Assert.IsTrue(results.All(x => x.Errors.Count == 0));
}
That's assuming that CreateTicketRequest uses Constructor Injection or Property Injection.
I am using Moq as my mocking framework. As per the code below, I have two mocks setup and I would like to setup the second to return the first mock. Is this possible and if so how would I go about doing it? At the moment it says the mock being returned is an invalid candidate.
[SetUp]
private void SetupMarketRow()
{
var marketTotalRow = new Mock<ITotalRow>();
marketTotalRow.Setup(r => r.TotalBudgetCurrentFact).Returns(1860716);
marketTotalRow.Setup(r => r.TotalBudgetEvol).Returns(-26);
marketTotalRow.Setup(r => r.TotalBudgetPreviousFact).Returns(2514079);
var localMarketReport = new Mock<IReport>();
localMarketReport.Setup(r => r.TotalRow).Returns(marketTotalRow);
// Red swiggley here saying invalid candidate
}
You can access the actual Mocked ITotalRow using marketTotalRow.Object.
[SetUp]
private void SetupMarketRow()
{
var marketTotalRow = new Mock<ITotalRow>();
marketTotalRow.Setup(r => r.TotalBudgetCurrentFact).Returns(1860716);
marketTotalRow.Setup(r => r.TotalBudgetEvol).Returns(-26);
marketTotalRow.Setup(r => r.TotalBudgetPreviousFact).Returns(2514079);
var localMarketReport = new Mock<IReport>();
localMarketReport.Setup(r => r.TotalRow).Returns(marketTotalRow.Object);
// Red swiggley here saying invalid candidate
}
Changing the interface declaration from
MarketTotalRow TotalRow { get; }
to...
ITotalRow TotalRow { get; }
fixed the problem.