Match a func delegate in argument matcher in nsubstitute Received method - c#

I am trying to check if a method is called a specific number of times on a mock instance of a class. The problem is the method has a func delegate and that is not matching.
I have the following scenario:
public interface ISomeService: IService
{
Task CleanupMethod(CancellationToken cancellationToken);
}
public interface I
{
Task invokedMethod(string aName, Func<IService, Task> action);
}
public class ClassGoingToBeUnitTested
{
// instance of I
private I instanceOfI;
// a list of names.
private static readonly string[] serviceNames =
{
"Name1",
"Name2"
};
// constructor
public ClassGoingToBeUnitTested(I passedInstance)
{
this.instanceOfI = passedInstance;
}
public void methodToBeUnitTested(object cancellationToken)
{
// my logic here
// here I am calling invokedMethod method to known number of times.
// something like this.
try
{
IEnumerable<Task> someTasks = serviceNames.Select(
name => this.instanceOfI.invokedMethod(
name,
service => ((ISomeService)service).CleanupMethod((CancellationToken)cancellationToken)
));
// here I run the tasks
Task.WaitAll(someTasks.ToArray());
}
catch
{
// proper catching of exceptions
}
// other logic
}
}
[TestClass]
public class ClassGoingToBeUnitTestedTest
{
// mock of I interface
private I IMock;
// ClassGoingToBeUnitTested object
ClassGoingToBeUnitTested classGoingToBeUnitTested;
[TestInitialize]
public void init()
{
this.IMock = Substitute.For<I>();
this.classGoingToBeUnitTested = new ClassGoingToBeUnitTested(this.IMock);
}
[TestMethod]
public void methodToBeUnitTested_Success()
{
// Arrange
var cancellationTokenSource = new CancellationTokenSource();
// Act
this.classGoingToBeUnitTested.methodToBeUnitTested(cancellationTokenSource.Token);
// Assert
// this is throwing exception.
this.IMock.Received(1).invokedMethod(
"Name1",
service => ((ISomeService)service).CleanupMethod((CancellationToken)cancellationTokenSource.Token)); // problem lies in this line.
}
}
In the above code if I change ((ISomeService)service).CleanupMethod((CancellationToken)cancellationTokenSource.Token)) to Arg.Any<Func<IService, Task>(), it runs perfectly. But I don't want to check that for my use case.
Till now, I have been able to debug that the argument matcher is matching the delegates by reference and hence is not able to match the arguments correctly. But I am not able to correctly match the arguments.
I also tried to invoke the delegate but I did not succeed. I think I am missing something. Any help would be highly appreciated.

I solved this by using Invoke. I first mocked the behaviour of invokedMethod to invoke a mocked serviceInstanceMock whenever it is called and then checked the number of times CleanupMethod is called on the serviceInstanceMock itself.
[TestClass]
public class ClassGoingToBeUnitTestedTest
{
// mock of I interface
private I IMock;
// mock of ISomeService
private ISomeService someServiceMockInstance;
// ClassGoingToBeUnitTested object
ClassGoingToBeUnitTested classGoingToBeUnitTested;
[TestInitialize]
public void init()
{
this.IMock = Substitute.For<I>();
this.ISomeService = Substitute.For<ISomeService>();
this.classGoingToBeUnitTested = new ClassGoingToBeUnitTested(this.IMock);
}
[TestMethod]
public void methodToBeUnitTested_Success()
{
// Arrange
var cancellationTokenSource = new CancellationTokenSource();
this.IMock.invokedMethod(
Arg.Any<string>,
Arg.Do<Func<IService, Task>(x => x.Invoke(this.someServiceMockInstance)));
// Act
this.classGoingToBeUnitTested.methodToBeUnitTested(cancellationTokenSource.Token);
// Assert
this.IMock.Received(1).invokedMethod(
"Name1",
Arg.Any<Func<IService, Task>()); // changed this
this.IMock.Received(1).invokedMethod(
"Name2",
Arg.Any<Func<IService, Task>()); // added this as well
// adding to check the Received call on the service instance
this.someServiceMockInstance.Received(2).CleanupMethod(cancellationTokenSource.Token);
}
}

Related

How to raise an event when unit testing asynchronous method in my case?

I use MS-Test, moq 4.18.2 and FileSystem (System.IO.Abstractions) 17.0.24 for my tests.
I think I wrote a correct test for InfoLoader_LoadInfoAsync. But, I don't understand how to write a test for MyViewModel::StartLoadInfoAsync to check that InfoList was populated correctly. It seems that I have to duplicate instantiation and configuration of InfoLoader as I did in InfoLoader_LoadInfoAsync. Is there a way around this? How such things are usually tested?
public abstract class IInfoLoader
{
public event Action<MyInfo> InfoLoaded;
public abstract Task LoadInfoAsync();
protected void OnInfoLoaded(MyInfo info)
{
InfoLoaded?.Invoke(info);
}
}
public class InfoLoader : IInfoLoader
{
private readonly IFileSystem _fileSystem;
private readonly string _path;
public InfoLoader(string path, IFileSystem fileSystem) {...}
public async override Task LoadInfoAsync()
{
foreach (var data in await _fileSystem.File.ReadAllLinesAsync(_path))
OnInfoLoaded(new MyInfo(...));
}
}
public class MyViewModel
{
private IInfoLoader _infoLoader;
public ObservableCollection<MyInfo> InfoList { get; }
public MyViewModel(IInfoLoader infoLoader) { ... }
public Task StartLoadInfoAsync()
{
_infoLoader.InfoLoaded += (info) => InfoList.Add(info);
return _infoLoader.LoadInfoAsync();
}
}
Tests
[TestMethod]
public async Task InfoLoader_LoadInfoAsync_Success()
{
var path = "...";
var lines = new string[] { "name1", "name2" };
var expectedInfoList = new List<MyInfo>();
foreach(var line in lines)
expectedInfoList.Add(new MyInfo(line));
var fileSystem = new Mock<IFileSystem>();
fileSystem.Setup(fs => fs.File.ReadAllLinesAsync(path, CancellationToken.None))
.ReturnsAsync(lines);
var actualInfoList = new List<MyInfo>();
var infoLoader = new InfoLoader(path, fileSystem.Object);
infoLoader.InfoLoaded += (info) => actualInfoList.Add(info);
await infoLoader.LoadInfoAsync();
// Assert that items in expectedInfoList and actualInfoList are equal
}
[TestMethod]
public async Task MyViewModel_StartLoadInfoAsync_Success()
{
var expectedInfoList = new List<MyInfo>();
// WHAT DO I DO HERE? DO I CREATE AND CONFIGURE infoLoader LIKE in "InfoLoader_LoadInfoAsync" TEST?
var vm = new MyViewModel(infoLoader.Object);
await vm.StartLoadInfoAsync();
actualInfoList = vm.InfoList;
// Assert that items in expectedInfoList and actualInfoList are equal
}
Since the view model depends on the IInfoLoader abstraction, it can be mocked to behave as expected when the desired member is invoked.
Review the comments in the following example
[TestMethod]
public async Task MyViewModel_StartLoadInfoAsync_Success() {
//Arrange
var info = new MyInfo();
List<MyInfo> expectedInfoList = new List<MyInfo>() { info };
// WHAT DO I DO HERE?
var dependency = new Mock<IInfoLoader>(); //mock the dependency
dependency
// When LoadInfoAsync is invoked
.Setup(_ => _.LoadInfoAsync())
// Use callback to raise event passing the custom arguments expected by the event delegate
.Callback(() => dependency.Raise(_ => _.InfoLoaded += null, info))
// Then allow await LoadInfoAsync to complete properly
.Returns(Task.CompletedTask);
MyViewModel subject = new MyViewModel(dependency.Object);
//Act
await subject.StartLoadInfoAsync();
//Assert
List<MyInfo> actualInfoList = subject.InfoList;
actualInfoList.Should().NotBeEmpty()
And.BeEquivalentTo(expectedInfoList); //Using FluentAssertions
}
Note how a Callback is used to capture when LoadInfoAsync is invoked by the subject so that an event can be raised by the mock, allowing the subject under test to flow to completion as desired
Reference MOQ Quickstart: Events
In order to test StartLoadInfoAsync you need an instance of MyViewModel, so you should:
Create this instance.
Invoke the method StartLoadInfoAsync.
Assert that its state is according to what you need.
Now obviously you have a dependency, which is InfoLoader, so you have two options:
Create and configure a new instance of InfoLoader
Mock InfoLoader so you can test MyViewModel independently of InfoLoader.
The second approach is what you may want to follow, this way you do not need to configure again InfoLoader, mock the FileSystem and so on.
You only need to create a mock of InfoLoader and setup its calls, just like you did with the FileSystem.

How can I determine if a function wrapped in an if statement gets called?

I have a class, like this one:
public class SomeClass: ISomeClass
{
public async Task<ServiceResponse> PerformAction(Context context)
{
if(IsPartner(context))
{
SendTextMessageAsync(context);
}
}
public bool IsPartner(Context context)
{
return SomeStaticHelperClass.GetIsPartner(context.PartnerId);
}
public async void SendTextMessageAsync(Context context)
{
// sends the message
}
}
ISomeClass exposes all three methods.
I'm using Moq and I would like to write a test that verifies
when IsPartner returns true
then SendTextMessage is called once.
I've tried everything I can think of.
This is my latest attempt:
public class ReceiptServiceTests
{
[Fact]
public async void SendReceiptsProofsNeededNudgeAsync_ShouldCallSendTextMessageAsync_WhenSessionPartnerIdIsNotNullOrEmptyString()
{
var context = new Context { PartnerId = "12345" };
var mockSomeClass = new Mock<ISomeClass>();
// force IsPartner to return true
mockSomeClass.Setup(m => m.IsPartner(context)).Returns(true);
// call PerformAction which should call SendTextMessageAsync
// because IsPartner will return true
await mockSomeClass.Object.PerformAction(context);
// verify SendTextMessageAsync was actually called
mockSomeClass.Verify(m => m.SendTextMessageAsync(It.IsAny<Context>()), Times.AtLeastOnce);
}
}
I keep getting following error:
(Expected invocation on the mock at least once, but was never performed: m => m.SendTextMessageAsync)
which i'm guessing is because SendTextMessageAsync is never called. I'm stuck here though, I don't understand how to properly call it.
I know some (or a lot) of this code doesn't make sense, I've changed it for brevity.
What I'm really just trying to figure out is how can I determine if a function (SendTextMessageAsync) is called when it is wrapped in an if statement that calls another function that returns true.
As rgvlee as already pointed out you can only mock dependencies and verify their method calls.
In your case SomeStaticHelperClass is your dependency and its GetIsPartner method that could be verified.
Unfortunately static classes are not good candidates for mocking. If you could replace that static class reference to an interface then you would be able to mock that easily.
SomeClass uses IPartnerService
public class SomeClass: ISomeClass
{
private readonly IPartnerService partnerSvc;
public SomeClass(IPartnerService partnerSvc)
{
this.partnerSvc = partnerSvc;
}
public async Task<ServiceResponse> PerformAction(Context context)
{
if(IsPartner(context))
{
SendTextMessageAsync(context);
}
}
public bool IsPartner(Context context)
{
return partnerSvc.GetIsPartner(context.PartnerId);
}
public async void SendTextMessageAsync(Context context)
{
// sends the message
}
}
SomeClass is using a IPartnerService mock during unit testing
public class ReceiptServiceTests
{
[Fact]
public async Task GivenAPartner_WhenICallPerformAction_ThenItCallsPartnerService()
{
//Arrange
const string partnerId = "12345";
var context = new Context { PartnerId = partnerId };
var partnerSvcMock = new Mock<IPartnerService>();
partnerSvcMock
.Setup(svc => svc.GetIsPartner(partnerId))
.Returns(true);
var SUT = new SomeClass(partnerSvcMock);
//Act
_ = await SUT.PerformAction(context);
//Assert
partnerSvcMock.Verify(svc => svc.GetIsPartner(partnerId), Times.Once);
}
}

Nunit: Testing legacy code (private void) method

I have been tasked with building unit tests for a bunch of legacy code. The specific task/goal for the below method is to test that the messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact) method is being called. I am also posting the test stub I have written so far but I would appreciate some direction because I think I am going down a rabbit hole here. How can I fill in the blanks on my test?
Method being tested:
private void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
var messageProcessor = new MessageProcessor();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Test:
[TestFixture, RequiresSTA]
class BucketBrowserTest
{
[Test]
public void logPhoneCallDialog_SaveContact()
{
//Arrange
//Act
//Assert
}
}
Method that calls above method
private void ShowPhoneCallLoggerDialog()
{
PhoneCallLoggerDialog dialog = new PhoneCallLoggerDialog(CurrentCustomer, CurrentBucket.BucketTypeId);
dialog.Owner = this;
dialog.SaveContact += new PhoneCallLoggerDialog.SaveContactHandler(logPhoneCallDialog_SaveContact);
dialog.ShowDialog();
}
Event Handler for calling method
public delegate void SaveContactHandler(PhoneContact currentPhoneContact);
public event SaveContactHandler SaveContact;
Based on the additional information you've supplied, I'm going to outline my assumptions before describing a possible solution:
You're able to safely construct an instance of this class, without calling anything out of process
Calling logPhoneCallDialog_SaveContact(), won't trigger side effects that prevent it from being tested
When refactoring legacy code, you often have to make design choices that you would normally avoid. This can include:
Testing implementation details
Making methods public or internal
Adding light abstractions that simply facilitate testing
In order to get a test around this, you're going to have to do at least one of those things.
Firstly, make logPhoneCallDialog_SaveContact public:
public void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
// same body as before
}
Next, extract a method that holds the entire body of the first one, to end up with this:
public void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
SaveContact(currentPhoneContact);
}
private void SaveContact(Contact currentPhoneContact)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
// This code from your example doesn't compile.
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
var messageProcessor = new MessageProcessor();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Make the new method public:
public void SaveContact(Contact currentPhoneContact)
{
// same body as before
}
If you haven't already, extract an interface for MessageProcessor:
public interface IMessageProcessor
{
ProcessCustomerPhoneContactInfo(Contact currentPhoneContact);
}
public class MessageProcessor : IMessageProcessor
{
public void ProcessCustomerPhoneContactInfo(Contact currentPhoneContact)
{
// implementation
}
}
Now modify the methods like so:
public void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
var messageProcessor = new MessageProcessor();
SaveContact(currentPhoneContact, messageProcessor);
}
public void SaveContact(
Contact currentPhoneContact,
IMessageProcessor messageProcessor)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Now write your unit tests against SaveContact, mocking IMessageProcessor, instead of against logPhoneCallDialog_SaveContact.
Edit
Here's an example, as requested. It's been a while since I've used Moq - which was in your original question - so the syntax may not be quite right, but something like this:
[Test]
public void SavesContact()
{
// Arrange
var contact = new Contact();
var messageProcessor = new Mock<IMessageProcessor>();
var subject = // whatever class contains the logPhoneCallDialog_SaveContact method
// Act
subject.SaveContact(contact, messageProcessor.Object);
// Assert
messageProcessor.Verify(x => x.ProcessCustomerPhoneContactInfo(contact), Times.Once());
}
Also test the case where contact is null.
With the code as it stands, you cannot mock out the messageProcessor, but with a few changes, you could:
IMessageProcessorFactory _messageProcessorFactory;
public TheConstructor(IMessageProcessorFactory processorFactory)
{
_messageProcessorFactory = processorFactory;
}
private void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
var messageProcessor = _messageProcessorFactory.Create();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Then you can Moq/Mock the interface and find out if the function was called.

How to mock an IEnumerable<interface> type and pass it to constructor

I got a class which looks like below
public interface ILocationProvider
{
bool IsRequiredLocation (string type);
}
public class MyClass : IMyInterface
{
private readonly IEnumerable<ILocationProvider> _locationProvider;
public MyClass (ILocationProvider[] locationProvider)
{
_locationProvider = locationProvider;
}
public ILocationProvider ProvideRequireLocationObject(string type)
{
ILocationProvider location = _locationProvider.FirstOrDefault(x => x.IsRequiredLocation(type));
return location;
}
}
Now I am trying to write some tests for it. But I stuck passing the Mock<IEnumerable<ITransitReportCountryFlowProvider>> to constructor. Below my test code
[TestClass]
public class TMyClassTest
{
private Mock<IEnumerable<ILocationProvider>> _locationProvider = null;
private IMyInterface _myClass = null;
[TestInitialize]
public void InitializeTest ()
{
_locationProvider = new Mock<IEnumerable<ILocationProvider>>();
}
[TestMethod]
public void ProvideRequireLocationObject_Test1()
{
//Given: I have type as 'PMI'
string type = "PMI";
//When: I call MyClass object
_myClass = new MyClass(_locationProvider.Object); //wrong actual argument as the formal argument is an array of ILocationProvider
//_locationProvider.Setup(x => x.IsRequiredCountryFlow(It.IsAny<string>())).Returns(true); //how do I setup
ILocationProvider result = _myClass.ProvideRequireLocationObject(type);
//Then: I get a type of ILocationProvider in return
Assert.IsTrue(result is ILocationProvider);
}
}
Problem 1: The line _myClass = new MyClass(_locationProvider.Object) in above test class, as the constructor's formal argument is ILocationProvider[] so I cannot pass a mocking object of Mock<IEnumerable<ILocationProvider>>
Problem 2: If I change the line private readonly IEnumerable<ILocationProvider> _locationProvider; in above MyClass to private readonly ILocationProvider[] _locationProvider; I will not be able to mock it as because mock must be an interface or an abstract or non-sealed class.
Problem 3: How do I set up for _locationProvider.FirstOrDefault(x => x.IsRequiredLocation(type)); in my test method
Problem 4: How do I assert that my method ProvideRequireLocationObject is returning a type of ILocationProvider
First of all, you don’t need to mock the collection. Collections (arrays or lists) are tested well enough to trust on their implementation. Since your constructor expects an array, you need to pass an array. And the simplest way to do that is to simply pass an array. There is no reason to mock this at all.
Changing the implementation details of the class you are testing (as suggested in problem 2) will not change anything on the testing surface. Unit tests should always be independent from the internal implementation details anyway.
How do I assert that my method ProvideRequireLocationObject is returning a type of ILocationProvider
You don’t need to do that. The method has that return type, so the compiler will only accept an implementation where the method returns that type. You are guaranteed by the language that if there is a return value, then it’s of the ILocationProvider type. So you actually just need to check for null.
Taking your implementation, below is a possible way to test this. Note that you don’t actually need to mock this. You usually mock things when the actual implementation is too difficult to set up (e.g. has other dependencies) or when providing a testable implementation is too much work (e.g. an interface with lots of method but you only need one). In this case, I’m assuming that the ILocationProvider is easy to implement, so we’re going to create a test type for this:
[TestClass]
public class MyClassTests
{
[TestMethod]
public void ProvideRequireLocationObject_EmptyCollection()
{
// arrange
var providers = new ILocationProvider[] {};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.IsNull(result);
}
[TestMethod]
public void ProvideRequireLocationObject_NoRequiredLocation()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(false)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.IsNull(result);
}
[TestMethod]
public void ProvideRequireLocationObject_OneRequiredLocation()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(true)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[0], result);
}
[TestMethod]
public void ProvideRequireLocationObject_OneRequiredLocationNotFirstInArray()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(false),
new TestLocationProvider(true),
new TestLocationProvider(false)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[1], result);
}
[TestMethod]
public void ProvideRequireLocationObject_MultipleRequiredLocations()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(true),
new TestLocationProvider(true),
new TestLocationProvider(true)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[0], result);
}
public class TestLocationProvider : ILocationProvider
{
public TestLocationProvider(bool isRequiredLocation)
{
IsRequiredLocation = isRequiredLocation;
}
public bool IsRequiredLocation { get; private set; }
}
}
Of course, you could expand those tests as necessary.
I believe are looking at it from the wrong angle. I think you don't need to mock the IEnumerable (Mock<IEnumerable<ITransitReportCountryFlowProvider>>) - IEnumerable has been testing front and back and besides you don't want to have to implement all its logic..
I think you should mock your own classes: Mock<ITransitReportCountryFlowProvider>
And pass a normal IEnumerable containing your mock in it
Something like:
[TestClass]
public class TMyClassTest
{
private Mock<ILocationProvider> _locationProvider = null;
private IEnumerable<ILocationProvider> _locationProviderCollection;
private IMyInterface _myClass = null;
[TestInitialize]
public void InitializeTest ()
{
_locationProvider = new Mock<IEnumerable<ILocationProvider>>();
_locationProviderCollection = new List<ILocationProvider> { _locationProvider };
}
[TestMethod]
public void ProvideRequireLocationObject_Test1()
{
//Given: I have type as 'PMI'
string type = "PMI";
//When: I call MyClass object
_myClass = new MyClass(_locationProviderCollection); //wrong actual argument as the formal argument is an array of ILocationProvider
.....
}
}

Moq with Task await

Since I have converted my WCF methods to Async, my unit tests have failed, and I can't figure out the correct syntax to get them to work.
Cllient proxy class
public interface IClientProxy
{
Task DoSomething(CredentialDataList credentialData, string store);
}
service class
public class CredentialSync : ICredentialSync
{
private ICredentialRepository _repository;
private IClientProxy _client;
public CredentialSync()
{
this._repository = new CredentialRepository();
this._client = new ClientProxy();
}
public CredentialSync(ICredentialRepository repository, IClientProxy client)
{
this._repository = repository;
this._client = client;
}
public async Task Synchronise(string payrollNumber)
{
try
{
if (string.IsNullOrEmpty(payrollNumber))
{
.... some code
}
else
{
CredentialDataList credentialData = new CredentialDataList();
List<CredentialData> credentialList = new List<CredentialData>();
// fetch the record from the database
List<GetCredentialData_Result> data = this._repository.GetCredentialData(payrollNumber);
var pinData = this._repository.GetCredentialPinData(payrollNumber);
// get the stores for this employee
var storeList = data.Where(a => a.StoreNumber != null)
.GroupBy(a => a.StoreNumber)
.Select(x => new Store { StoreNumber = x.Key.ToString() }).ToArray();
var credential = this.ExtractCredentialData(data, pinData, payrollNumber);
credentialList.Add(credential);
credentialData.CredentialList = credentialList;
foreach (var store in storeList)
{
//this line causes an Object reference not set to an instance of an object error
await _client.DoSomething(credentialData, store.StoreNumber);
}
}
}
catch (Exception ex)
{
throw new FaultException<Exception>(ex);
}
}
Test Class
/// </summary>
[TestClass]
public class SynchTest
{
private Mock<ICredentialRepository> _mockRepository;
private Mock<IClientProxy> _mockService;
[TestInitialize]
public void Setup()
{
... some setups for repository which work fine
}
[TestMethod]
public async Task SynchroniseData_WithOneEmployee_CallsReplicateService()
{
this._mockService = new Mock<IClientProxy>();
this._mockService.Setup(x=>x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()));
// arrange
string payrollNumber = "1";
CredentialSync service = new CredentialSync(this._mockRepository.Object, this._mockService.Object);
// act
await service.Synchronise(payrollNumber);
// assert
this._mockService.VerifyAll();
}
The error is when ClientProxy.DoSomething is called:
Object reference not set to an instance of an object
The parameters are both fine.
If I convert my ClientProxy.DoSomething method to a synchronous method
(public void DoSomething(...) )the code works fine, but I do need this to be called asynchronously
DoSomething returns null instead of returning a Task, and so you get an exception when awaiting it. You need to specify when building the mock that it should return a Task.
In this case it seems that you can simply return an already completed task using Task.FromResult so the mock setup should look like this:
this._mockService.Setup(...).Returns(Task.FromResult(false));
Beginning with the next version of .Net (4.6) you can use Task.CompletedTask like this:
this._mockService.Setup(...).Returns(Task.CompletedTask);
You can reduce the amount of clutter in the code by using ReturnsAsync
this._mockService.Setup(...).ReturnsAsync(false);
This way you can remove the Task.FromResult part of the code
I think you need to return the Task from the DoSomething mock
this._mockService.Setup(x => x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()))
.Returns(Task.FromResult<int>(0));

Categories

Resources