im trying to write unit tests for a class that is written using reactivex.io .
my test code is something like this:
[TestMethod]
public void TestMethod1()
{
string userName = "Moeen";
string password = "moeen123";
string instrument = "Bass";
_loggerMock = new Mock<ILogger>();
_loggerMock.Setup(x => x.RequestInput(Messages.EnterUsername)).Returns(Observable.Return(userName));
_loggerMock.Setup(x => x.RequestInput(Messages.EnterPassword)).Returns(Observable.Return(password));
// _loggerMock.Setup(x => x.ShowProgressIndicator("loading")).Returns(ValueFunction);
var options = Enum.GetValues(typeof(Instrument)).Cast<Instrument>().Select(val => val.ToString());
_loggerMock.Setup(x => x.RequestInput($"{Messages.SelectInstrument} [{string.Join("|", options)}]")).Returns(Observable.Return(instrument));
_loggerMock.Setup(x => x.ShowMessage(""));
_backendMock = new UnreliableFakeBackend();
var result = new SignupFlow(_backendMock, _loggerMock.Object).Run();
result.Subscribe(x =>
{
Assert.AreEqual(true,false);
});
I tested it but the Assert code never gets called inside the subscribe function so the function always asserts true.
as I read the docs I have to write a scheduler to make it work but it doesn't explain well enough to make it work.
Related
I have a method
Task<Document> GetCampaignById(Tenant tenant, string language, string campaignId);
that I am trying to mock:
mockLocator.Setup(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns(Task.FromResult(dummy));
I did, at first have "not set up" output but I am not getting any at all now and the test just shows as failed. I have tried changing to ReturnsAsync(dummy) but that did not alter my output at all. moq is set to strict but I don't think that should matter.
As far as I can tell I am setting this up with the correct parameter types and the correct return type but the test seems to fail before it even starts. Can anyone shed any light on this?
Full Test
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
[TestCase(4)]
[TestCase(5)]
public async Task ShouldCallUpdaterForEveryTenantResolved(int tupleCount)
{
// Arrange
var tenantTuples = CreateTenantTuples(tupleCount);
var mockTenantResolver = MockRepository.Create<ITenantResolver>();
mockTenantResolver.Setup(tr => tr.GetTenantTuples(It.IsAny<string>()))
.Returns(tenantTuples);
var mockCampaignIngestionService = MockRepository.Create<ICampaignIngestionService>();
var dummy = new Document();
var mockLocator = MockRepository.Create<IVehicleSearchStockUpdater>();
mockLocator.Setup(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns(Task.FromResult(dummy));
mockLocator.Setup(l => l.UpsertNewStockLevel(
It.IsAny<Document>(),
It.IsAny<OmegaConnector.Functions.PartnerCommunicator.Models.ChangeStockInfo>()))
.Returns(Task.FromResult(dummy));
var sut = new CampaignIngestionProcessor(
mockTenantResolver.Object,
mockCampaignIngestionService.Object,
mockLocator.Object);
var data = GetSimpleTestData();
data.NewStock = 5;
// Act
await sut.SubmitChangeStock(data);
// Assert
mockLocator.Verify(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()),
Times.Exactly(tupleCount)
);
mockLocator.Verify(l => l.UpsertNewStockLevel(
It.IsAny<Document>(),
It.IsAny<OmegaConnector.Functions.PartnerCommunicator.Models.ChangeStockInfo>()),
Times.Exactly(tupleCount)
);
}
How can I test the DeleteAppointmentById here?
Func<IDataAdapterRW, IEnumerable<uint>> function = db => DeleteAppointmentById(db, appointmentId);
return _dataContextProvider.GetContextRW().Run(function);
_dataContextProvider is mocked with moq. If I run the test it never enters DeleteAppointmentById of course
The method to test:
public IEnumerable<uint> DeleteAppointment(uint appointmentId)
{
Func<IDataAdapterRW, IEnumerable<uint>> function = db => DeleteAppointmentById(db, appointmentId);
return _dataContextProvider.GetContextRW().Run(function);
}
DeleteAppointmentById is the inner method (private) I am really interested in.
my test:
[Test]
public void DeleteAppointment_Valid_DeletedRecordId()
{
//Setup
var dbContextMock = new Mock<IDataContextProvider>();
var dataAdapterMock = new Mock<IDataContext<IDataAdapterRW>>();
dbContextMock.Setup(d => d.GetContextRW())
.Returns(dataAdapterMock.Object);
dataAdapterMock.Setup(a => a.Run(It.IsAny<Action<IDataAdapterRW>>()));
var calendarService = new CalendarService(dbContextMock.Object);
//Run
var result = calendarService.DeleteAppointment(1);
//Assert
Assert.AreEqual(1, result);
}
You can access the result of the Func passed as parameter in Run method, and to Assert the result like below.
Why to return the result? Because it's a mock and don't know how Run method is behaving.
[Test]
public void DeleteAppointment_Valid_DeletedRecordId()
{
//Setup
var dbContextMock = new Mock<IDataContextProvider>();
var dataAdapterMock = new Mock<IDataContext<IDataAdapterRW>>();
dbContextMock.Setup(d => d.GetContextRW())
.Returns(dataAdapterMock.Object);
dataAdapterMock.Setup(a => a.Run(It.IsAny<Func<IDataAdapterRW, IEnumerable<uint>>>()))
.Returns((Func<IDataAdapterRW, IEnumerable<uint>> func) => { return func(dataAdapterMock.Object);}); // configure the mock to return the list
var calendarService = new CalendarService(dbContextMock.Object);
//Run
int id = 1;
var result = calendarService.DeleteAppointment(id);
//Assert
var isInList = result.Contains(id); // verify the result if contains the
Assert.AreEqual(isInList, true);
}
Unit tests tend to take the following structure:
Arrange: set up the context. In this case, you'd probably create an appointment and save it to the database.
Act: call the unit you're testing. In this case, DeleteAppointmentById(db, appointment).
Assert: check if side effects and returns were correct. In this case, you may attempt to load this appointment from the database, and assert that you were unable (because it should have been deleted).
is it possible to assert whether a method has been called? I'm testing the following method and I want to assert that the _tokenManager.GetToken() has been called. I just want to know if the method has been called as the method does not return a value. I am using Moq.
Thanks,
Code snippet
public void Subscribe(string code, string emailAddress, string columnKey)
{
// Request authentication token
var token = _tokenManager.GetToken(code, false);
if (!_tokenValidator.Validate(token))
{
// Token has expired or invalid - refresh the token
token = _tokenManager.GetToken(code, true);
}
// Subscribe email
_silverpopRepository.Subscribe(token.AccessToken, emailAddress, columnKey);
}
You should mock TokenManager and TokenValidator, and then create two unit test cases:
Case 1: token is validated and GetToken is called exactly once
Case 2: token is not validated and GetToken is called exactly twice
Case 1:
[Test]
public void Subscribe_TokenIsValidated_GetTokenIsCalledOnce()
{
// Arrange:
var tokenManagerMock = Mock.Of<TokenManager>();
var tokenValidatorMock = Mock.Of<TokenValidator>(x =>
x.Validate(It.IsAny<Token>()) == true);
var subscriber = new Subscriber
{
TokenManager = tokenManagerMock,
TokenValidator = tokenValidatorMock
};
// Act:
subscriber.Subscribe(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>());
// Assert:
Mock.Get(tokenManagerMock).Verify(x =>
x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.Once);
}
Case 2:
[Test]
public void Subscribe_TokenIsExpiredOrInvalid_GetTokenIsCalledTwice()
{
// Arrange:
var tokenManagerMock = Mock.Of<TokenManager>();
var tokenValidatorMock = Mock.Of<TokenValidator>(x =>
x.Validate(It.IsAny<Token>()) == false);
var subscriber = new Subscriber
{
TokenManager = tokenManagerMock,
TokenValidator = tokenValidatorMock
};
// Act:
subscriber.Subscribe(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>());
// Assert:
Mock.Get(tokenManagerMock).Verify(x =>
x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.Exactly(2));
}
Alternatively, you can create an unit test without mocking TokenValidator and verify if GetToken() has been called at least once. However, creating two cases as in the first example is preferred as we are testing all code paths.
// Arrange:
var tokenManagerMock = Mock.Of<TokenManager>();
var subscriber = new Subscriber {TokenManager = tokenManagerMock};
// Act:
subscriber.Subscribe(It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>());
// Assert:
Mock.Get(tokenManagerMock).Verify(x =>
x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.AtLeastOnce);
Read more about verification in Moq at:
Moq quick start at official website
Verifying the Number of Calls to a Mocked Method at BlackWasp
You can verify using MOQ using the Verify method. Like this:
var tokenManagerMock = new Mock<ITokenManager>();
var sut = new WhateverItIsCalled(tokenManagerMock.Object);
sut.Subscribe("ssss", "example#example.com", "XXX");
tokenManagerMock.Verify(m => m.GetToken(It.Is<string>(c => c == "ssss", It.Is<bool>(x => x == false)), Times.Once);
You need to be able to pass the token manager into your system under test somehow. Usually via the ctor or maybe a property.
I would suggest you use something like AutoFixture to remove the ugliness that is "ssss" and make things a bit more DRY.
You may need to make the token manager mock return something appropriate too that will pass the validation. Something like this:
var tokenManagerMock = new Mock<ITokenManager>();
tokenManagerMock.Setup(m => m.GetToken(It.Is<string>(x => x == "ssss", It.IsAny<bool>()).Returns("XXXXXX");
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.