I'm trying to test with Microsoft Fakes code in a application which sort of the following construction in a library:
public static class C
{
public A GetConfigurationFactory(Uri uri);
}
public class A : B
{
public A(Uri uri)
{
}
}
public class B
{
public void Authenticate()
{
}
}
I've created the following test for this in Visual Studio:
//Arrange
ShimA.ConstructorUri = (#this, value) =>
{
var shim = new ShimA(#this);
};
ShimC.GetConfigurationFactory = (uri) =>
{
var shim = new A(uri);
return shim;
};
var uri1 = new Uri("http://test-url");
//Act
A.Authenticate()
I get a null pointer when I call the Authenticate method from instance A.
Does anyone how I can solve this? I already looked and there is no overloaded constructor.
Solved this problem with the following code:
ShimB.AllInstances.Authenticate = (someValue) => { return; }
This code ensures that when I call the Authenticate method from any class it will always return the specified value.
Related
I'm developing an API which communicates with MongoDB and I need to create some statistics from one collection. I have the following service:
public class BoxService : IBoxService
{
private readonly IMongoCollection<Box> _boxCollection;
public BoxService(IOptions<DbSettings> dbSettings, IMongoClient mongoClient)
{
var mongoDatabase = mongoClient.GetDatabase(dbSettings.Value.DatabaseName);
_boxCollection = mongoDatabase.GetCollection<Box>(dbSettings.Value.BoxCollectionName);
}
public async Task<List<BoxStatisticsDto>> GetBoxNumberStatisticsAsync()
{
var boxNumberStatisticsList = new List<BoxStatisticsDto>();
var results = await _boxCollection.AsQueryable()
.Select(box => new { box.WarehouseId, Content = box.Content ?? string.Empty })
.ToListAsync();
// More calculations with the results list
return boxNumberStatisticsList;
}
}
And the following test:
public class BoxServiceTest
{
private readonly IMongoCollection<Box> _boxCollection;
private readonly List<Box> _boxes;
private readonly IBoxService _boxService;
public BoxServiceTest()
{
_boxCollection = A.Fake<IMongoCollection<Box>>();
_boxes = new List<Box> {...};
var mockOptions = A.Fake<IOptions<DbSettings>>();
var mongoClient = A.Fake<IMongoClient>();
var mongoDb = A.Fake<IMongoDatabase>();
A.CallTo(() => mongoClient.GetDatabase(A<string>._, default)).Returns(mongoDb);
A.CallTo(() => mongoDb.GetCollection<Box>(A<string>._, default)).Returns(_boxCollection);
_boxService = new BoxService(mockOptions, mongoClient);
}
}
This is working so far, the BoxService is created with the fake parameters and I can test other functionalities of the service (FindAll, FindById, Create, etc.) but how can I test the GetBoxNumberStatisticsAsync function? I can't fake the AsQueryable because it's an extension method.
As you've noted, you can't fake an extension method. This question is asked every once in a while. For example, see Faking an Extension Method in a 3rd Party Library. There are a few approaches:
if the static method is simple enough, to divine what it does and fake the non-static methods that it calls
add a layer of indirection: wrap the call to the extension method in an interface that you can fake
don't fake the database. Instead, replace it with some in-memory analogue, if one exists (I don't know what's available for Mongo)
Here is what I ended up with. A base interface for all my services:
public interface IBaseService<T>
{
//generic method definitions for all services: Findall, FindById, Create, Update
}
An abstract class to have a generic constructor:
public abstract class BaseService<T> : IBaseService<T>
{
protected BaseService(IOptions<DbSettings> dbSettings, IMongoClient mongoClient, string collectionName)
{
var mongoDatabase = mongoClient.GetDatabase(dbSettings.Value.DatabaseName);
Collection = mongoDatabase.GetCollection<T>(collectionName);
}
protected IMongoCollection<T> Collection { get; }
// abstract method definitions for IBaseService stuff
public virtual async Task<List<T>> CollectionToListAsync()
{
return await Collection.AsQueryable().ToListAsync();
}
}
An interface for my BoxService:
public interface IBoxService : IBaseService<Box>
{
public Task<List<BoxStatisticsDto>> GetBoxNumberStatisticsAsync();
}
The service itself:
public class BoxService : BaseService<Box>, IBoxService
{
public BoxService(IOptions<DbSettings> dbSettings, IMongoClient mongoClient)
: base(dbSettings, mongoClient, dbSettings.Value.BoxCollectionName)
{
}
public async Task<List<BoxStatisticsDto>> GetBoxNumberStatisticsAsync()
{
var boxNumberStatisticsList = new List<BoxStatisticsDto>();
var list = await CollectionToListAsync();
var results = list.Select(box => new { box.WarehouseId, Content = box.Content ?? string.Empty }).ToList();
//...
return boxNumberStatisticsList;
}
}
And finally the test:
public async Task GetBoxNumberStatisticsAsync_ReturnsStatistics()
{
// Arrange
var expected = new List<BoxStatisticsDto> {...};
var fakeService = A.Fake<BoxService>(options => options.CallsBaseMethods());
A.CallTo(() => fakeService.CollectionToListAsync()).Returns(_boxes);
// Act
var boxList = await ((IBoxService)fakeService).GetBoxNumberStatisticsAsync();
// Assert
}
I'm not a huge fan of making the CollectionToListAsync public, but nothing really worked for me here. I tried creating IQueryable and IEnumerable from my list and convert them to IMongoQueryable but no success. I also tried faking the IMongoQueryable but I couldn't execute the Select on it as it gave an error that the 'collectionNamespace' can't be null and the CollectionNamespace can't be faked, because it's a sealed class.
Anyone have any idea why below still calls YesService?
It almost seems like IYesService is considered separate to YesService..
Any ideas?
public interface IYesService
{
string Hello();
}
public class YesService : IYesService
{
public string Hello()
{
return "Yes";
}
}
class Program
{
static void Main(string[] args)
{
var _mock = new Mock<IYesService>();
_mock.Setup(x => x.Hello()).Returns("No");
var service = new YesService();
var result = service.Hello();
Console.Write(result);
Console.ReadLine();
}
}
Because you don't use the _mock, you instantiate the YesService and call the method on that.
You can use mocking when you consume this interface:
public class ServiceUser
{
private IYesService _yesService;
public ServiceUser(IYesService yesService)
{
_yesService = yesService;
}
public string CallService()
{
return _yesService.Hello();
}
}
Then use it like this:
var serviceMock = new Mock<IYesService>();
serviceMock.Setup(x => x.Hello()).Returns("No");
var service = new ServiceUser(serviceMock.Object);
var result = service.CallService();
You are creating an instance of YesService (the concrete class) in your Main method. The var service line an be done away with, and the var result line should become:
var result = _mock.Object.Hello();
Try that...
I have a facade class that uses a WCF client proxy. To prevent issues with the WCF proxy client with IDispose (bug in WCF, still not fixed by MS), I have created a generic proxy service to do the basic plumbing for calling the WCF service.
I want to unit test the facade with Moq, and I have an issue how to get into specific call within a unit test using Moq. The unit test wants to verify that the call to the process manager was done just once, but the code does not flow within the 'Use' method....
(edit)
For completeness here is the part that fixed the issue:
public AuthenticationFacade CreateSut()
{
ProcessManager = new Mock<IProcessManager>().Object;
SessionWrapper = new Mock<ISessionWrapper>().Object;
AuthenticationClientProxy = new Mock<Action<IAuthentication>>().Object;
var authenticationProxyServiceMock = new Mock<IProxyService<IAuthentication>>();
Mock<IAuthentication> mockAuthentication = new Mock<IAuthentication>();
authenticationProxyServiceMock.Setup(aps => aps.Use(It.IsAny<Action<IAuthentication>>()))
.Callback<Action<IAuthentication>>(ac => ac(mockAuthentication.Object));
AuthenticationProxyService = authenticationProxyServiceMock.Object;
return new AuthenticationFacade(ProcessManager, SessionWrapper, AuthenticationProxyService);
}
(reference code)
Code part 1:
using System;
namespace Progis.Kim
{
public interface IProxyService<T>
{
void Use(Action<T> action);
}
}
Code part 2:
/// <summary>
/// Helper class to fix the WCF Client Proxy usage bug with IDispose.
/// Check: http://benmccallum.wordpress.com/2011/08/27/wcf-web-service-wrapper-closing-disposing-and-aborting-best-practices/
/// </summary>
/// <typeparam name="T"></typeparam>
public class ProxyService<T> : IProxyService<T>
{
public void Use(Action<T> action)
{
<cut>....
}
}
Code part 3:
public class AuthenticationFacade : IAuthenticationFacade
{
private readonly IProcessManager processManager;
private readonly ISessionWrapper sessionWrapper;
private readonly IProxyService<IAuthentication> authenticationProxyService;
public AuthenticationFacade(
IProcessManager processManager,
ISessionWrapper sessionWrapper,
IProxyService<IAuthentication> authenticationProxyService)
{
this.processManager = processManager;
this.sessionWrapper = sessionWrapper;
this.authenticationProxyService = authenticationProxyService;
}
public bool ValidateGebruiker(string gebruikernaam, string wachtwoord)
{
bool authenticated = false;
authenticationProxyService.Use(client =>
{
var sessionId = processManager.GetSessionId();
authenticated = client.ValidateGebruiker(
sessionId,
gebruikernaam,
wachtwoord);
});
return authenticated;
}
Code part 4:
public class AuthenticationFacadeFixture
{
public IProcessManager ProcessManager { get; set; }
public ISessionWrapper SessionWrapper { get; set; }
public IProxyService<IAuthentication> AuthenticationProxyService { get; set; }
public AuthenticationFacade CreateSut()
{
ProcessManager = new Mock<IProcessManager>().Object;
SessionWrapper = new Mock<ISessionWrapper>().Object;
AuthenticationProxyService = new Mock<IProxyService<IAuthentication>>().Object;
return new AuthenticationFacade(ProcessManager, SessionWrapper, AuthenticationProxyService);
}
}
Code part 5:
public static class MockExtensions
{
public static Mock<T> AsMock<T>(this T obj) where T : class
{
return Mock.Get(obj);
}
}
Code part 6 (unit test):
[TestMethod]
public void ValidateGebruiker_calls_processmanager_getsessionid_once()
{
// Arrange
var fixture = new AuthenticationFacadeFixture();
var sut = fixture.CreateSut();
var validUserPass = CreateValidGebruikersnaamWachtwoord();
// Act
sut.ValidateGebruiker(validUserPass.Gebruikersnaam, validUserPass.Wachtwoord);
// Assert
fixture.ProcessManager.AsMock().Verify(pm => pm.GetSessionId(), Times.Once());
}
You've omitted your Moq setup code which makes this a little harder, but I believe it looks something like this:
AuthenticationProxyService.Setup(a => a.Use(It.IsAny<Action<IAuthentication>>()));
If so, you can do the following:
// Not sure if you have this mock already, this is the "client" variable
// in your Use method action
Mock<IAuthentication> mockAuthentication = mockRepository.Create<IAuthentication>();
AuthenticationProxyService.Setup(a => a.Use(It.IsAny<Action<IAuthentication>>()))
.Callback<Action<IAuthentication>>(a => a(mockAuthentication.Object));
The Callback method receives the parameter from the Setup (an Action<IAuthentication>) which in this case is the code in ValidateGebruiker, and just invokes it with a mocked IAuthentication object (which you'll need to Setup if you don't already).
I have the below method:
public void Enqueue(ICommand itemToQueue)
{
if (itemToQueue == null)
{
throw new ArgumentNullException("itemToQueue");
}
// Using the dynamic keywork to ensure the type passed in to the generic
// method is the implementation type; not the interface.
QueueStorage.AddToQueue((dynamic)itemToQueue);
}
With QueueStorage being a dependency that implements IQueueStorage. I wish to unit test it but the (dynamic) keyword seems to be blocking Moq from binding correctly to it. The keyword is used to correctly assign the concrete class type rather than ICommand interface type when it is added to the queue.
The unit test looks like this:
[Test]
public void Enqueue_ItemGiven_AddToQueueCalledOnQueueStorage()
{
int timesAddToQueueCalled = 0;
var dummyQueueStorage = new Mock<IQueueStorage>();
var testCommand = new TestCommand();
var queueManager = new AzureCommandQueueManager();
dummyQueueStorage
.Setup(x => x.AddToQueue(It.IsAny<TestCommand>()))
.Callback(() => timesAddToQueueCalled++);
queueManager.QueueStorage = dummyQueueStorage.Object;
queueManager.Enqueue(testCommand);
Assert.AreEqual(1, timesAddToQueueCalled);
}
Whilst test command is a blank implementation of ICommand:
private class TestCommand : ICommand
{
}
public interface ICommand
{
}
The timesAddedToQueuCalled is not being incremented. I've tried using It.IsAny<ICommand> and (testCommand) to no avail. It looks like the Callback method is not being executed. Can anyone see what I'm doing wrong?
EDIT: IQueueStorage code:
public interface IQueueStorage
{
void AddToQueue<T>(T item) where T : class;
T ReadFromQueue<T>() where T : class;
}
Here is code which works without problems:
public class AzureCommandQueueManager
{
public void Enqueue(ICommand itemToQueue)
{
if (itemToQueue == null)
throw new ArgumentNullException("itemToQueue");
QueueStorage.AddToQueue((dynamic)itemToQueue);
}
public IQueueStorage QueueStorage { get; set; }
}
public interface IQueueStorage
{
void AddToQueue<T>(T command) where T : class;
}
public class TestCommand : ICommand {}
public interface ICommand {}
And test method:
[Test]
public void Enqueue_ItemGiven_AddToQueueCalledOnQueueStorage()
{
int timesAddToQueueCalled = 0;
var dummyQueueStorage = new Mock<IQueueStorage>();
var testCommand = new TestCommand();
var queueManager = new AzureCommandQueueManager();
dummyQueueStorage
.Setup(x => x.AddToQueue(It.IsAny<TestCommand>()))
.Callback(() => timesAddToQueueCalled++);
queueManager.QueueStorage = dummyQueueStorage.Object;
queueManager.Enqueue(testCommand);
Assert.AreEqual(1, timesAddToQueueCalled);
}
The only difference I see - you have private modifier of TestCommand class. Btw if it is private, how do you access that class from your tests?
I've have searched on this and it seems to be a catch all, unfortunately everything I've read doesn't help figure it out. Here is the class:
public interface IMockInterface
{
MockClass MockedMethod();
MockClass MockThis();
}
public class MockClass : IMockInterface
{
public virtual MockClass MockedMethod()
{
MockClass returnValue;
returnValue = new MockClass();
returnValue.SomeMessage = "Not mocked";
return returnValue;
}
public MockClass MockThis()
{
MockClass mock;
MockClass returnValue;
mock = new MockClass();
return mock.MockedMethod();
}
}
And the test:
public void MockTest_Internal()
{
MockClass mainClass;
MockClass returnedClass;
IMockInterface mockProvider;
mainClass = new MockClass();
mockProvider = repository.StrictMock<IMockInterface>();
Expect.Call(mockProvider.MockedMethod())
.Return(new MockClass { SomeMessage = "Mocked" });
repository.ReplayAll();
returnedClass = mainClass.MockThis();
provider.AssertWasCalled(item => item.MockedMethod());
Assert.IsTrue(returnedClass.SomeMessage == "Mocked");
}
And have also tried and doesn't work
But I keep getting this exception:
Rhino.Mocks.Exceptions.ExpectationViolationException:
IMockInterface.MockedMethod(); Expected #1, Actual #0
Now from what I've read this would suggest either the method was called with different than expected parameters OR the method was never called but was expected to be called. This isn't the case for the test.
Side Note: This is my first time really using Rhino.Mocks without some in house code so I am basically picking it up as I go. There could be something really stupid here...
This was the old test commented on, but is not what I should have been using:
public void MockTest_Internal()
{
MockClass mainClass;
MockClass returnedClass;
IMockInterface mockProvider;
mainClass = new MockClass();
var provider = MockRepository.GenerateStub<IMockInterface>();
provider.Stub(item => item.MockedMethod())
.Return(new MockClass { SomeMessage = "Mocked" });
returnedClass = mainClass.MockThis();
provider.AssertWasCalled(item => item.MockedMethod());
Assert.IsTrue(returnedClass.SomeMessage == "Mocked");
}
You're telling the mock framework to stub the MockedMethod class on the provider object, but you never inject the provider into the mainClass object to be used. It's not clear to me what you are trying to accomplish but if you want the mocked method to be called then it has to be called on the object on which the stub was set up.
If you define MockThis as below, I think you will find that it will work.
public MockClass MockThis(IMockInterface provider)
{
return provider.MockMethod();
}
The bottom line is that you get the exception because the method was never called on the provider, only on the mainClass object.
EDIT: Example
public class ClassUnderTest
{
private ProviderClass provider { get; set; }
public ClassUnderTest( ProviderClass provider )
{
this.Provider = provider;
}
public int DoOperation()
{
return this.Provider.ProviderOperation();
}
}
public class ProviderClass
{
private int value = 42;
public ProviderClass()
{
}
public virtual int ProviderOperation()
{
return this.value;
}
}
[TestMethod]
public void DoOperationTest()
{
ProviderClass mockProvider = MockRepository.GenerateMock<ProviderClass>();
mockProvider.Expect( mp => mp.ProviderOperation() ).Return( -1 );
ClassUnderTest target = new ClassUnderTest( mockProvider );
int expectedValue = -1;
int value = target.DoOperation();
Assert.AreEqual( expectedValue, value );
mockProvider.VerifyAllExpectations();
}
Normally the ProviderClass object would return 42 from the ProviderOperation method, but we've mocked it out and told it to return -1. When the ClassUnderTest DoOperation method is called, the mock provider object's ProviderOperation method is invoked and returns the mocked value of -1.
Hope this helps.
I usually get this error when a stubbed method is called with an object argument that I build in the test and in the tested code the object is built before calling that method. The solution is to use the Rhino.Mocks Matches().
Ex:
Arg<string>.Matches(s => s.Contains("some substring"))