Hi I am getting an error and I don't understand why
[SetUp]
public void Setup()
{
visitService = new Mock<IVisitService>();
visitRepository = new Mock<IVisitRepository>();
visitUIService = new VisitUIService(visitRepository.Object, visitService.Object);
}
[Test]
public void VisitUIService_CanSoftDelete()
{
Mock<IVisitEntity> mockVisitEntity = new Mock<IVisitEntity>();
visitService = new Mock<IVisitService>();
visitRepository.Setup(x => x.GetVisitsByDocumentLineItems(It.IsAny<IEnumerable<int>>())).Returns(new List<IVisitEntity>() { mockVisitEntity.Object});
visitUIService.DeleteVisits(new VisitDeletionModel());
visitService.Verify(x => x.SoftDeleteVisit(It.IsAny<IVisitEntity>()),Times.AtLeastOnce());
}
Invocation was not performed on the mock: x => x.SoftDeleteVisit(IsAny())
I can't fix this I added visitService.Setup(x => x.SoftDeleteVisit(mockVisitEntity.Object)).Verifiable(); and a few other variations of the parameters but no luck
thank you
I think the problem is the consuming object visitUIService is already been initialized with the intial mocked interfaces and the setup that you are doing later is not useful.
Two approaches:
a) move the initialization of the class to the test i.e after the interface is setup
b) Lazy Load the mocks as follows, but you need to modify your class for the same using Func or Lazy. I will show it using Func
visitUIService = new VisitUIService(()=>visitRepository.Object, ()=>visitService.Object);
Related
I have two ViewModels, MainWindowShellViewModel(shellVm) and MainWindowContentViewModel(contentVm). The shellVm publishes an event and the contentVm subscribes to it.
The shell VM looks something like the following. I have omitted many details.
// ctor
public MainWindowShellViewModel(IEventAggregator eventAggregator)
{
_EventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(IEventAggregator) + " service injected is null!!!");
_AppStartingClosingEventToken = _EventAggregator.GetEvent<AppStartingClosingEvent>();
}
private void MainWindowShellLoaded()
{
var payload = new AppStartingClosingEventData();
payload.Data = "MainWindowStarting";
_AppStartingClosingEventToken.Publish(payload);
}
The AppStartingClosingEvent is a no brainer type as follows.
public class AppStartingClosingEvent : PubSubEvent<AppStartingClosingEventData>
{ }
public class AppStartingClosingEventData
{
public string Data { get; set; }
}
And finally, the contentVm looks as follows.
public MainWindowContentViewModel(IEventAggregator eventAggregator)
{
_AppClosingEventToken.Subscribe(AppStartingClosing);
}
private void AppStartingClosing(AppStartingClosingEventData appStartingClosingEventData)
{
if (appStartingClosingEventData.Data == "MainWindowStarting")
LoadState(appStartingClosingEventData);
if (appStartingClosingEventData.Data == "MainWindowClosing")
SaveState(appStartingClosingEventData);
}
I want to test the that the method AppStartingClosing inside of contentVm is called with proper data. I am using Moq
I am running out of ideas. Please suggest. Tried the following but so far no success.
How do I test Prism event aggregator subscriptions, on the UIThread?
Using Moq to verify a Prism event subscription fails
Unit testing with Moq, Prism 6, and Event Aggregation
Moq Event Aggregator Is it possible
// Verifying a delegate was called with Moq
EDIT
Here is what I have tried.
// Arrange
var mockingKernel = new MoqMockingKernel();
var eventAggregatorMock = mockingKernel.GetMock<IEventAggregator>();
var eventBeingListenedTo = new AppStartingClosingEvent();
eventAggregatorMock.Setup(e => e.GetEvent<AppStartingClosingEvent>()).Returns(eventBeingListenedTo);
var vm = mockingKernel.Get<MainWindowContentViewModel>();
var evData = new AppStartingClosingEventData();
evData.Data = "MainWindowStarting";
// Act
eventBeingListenedTo.Publish(evData);
Now, what should I do? I am not even clear if I have approached correctly.
Now what should I do?
After eventBeingListenedTo.Publish(evData); look whether whatever effect SaveState should have is actually happening.
I am not even clear if I have approached correctly.
You do not want to test whether one method in a class is called by another method of that class.
So instead of trying to do
subjectUnderTest.DoStuff();
MagicallyVerifyThatThisGotCalled( () => subjectUnderTest.SomeEffect() );
you should do
var subjectUnderTest = new SubjectUnderTest( serviceMock.Object );
subjectUnderTest.DoStuff();
serviceMock.Verify( x => x.SomeEffectOnTheService(), Times.Once );
Assert.That( subjectUnderTest.SomePropertyThatsChanged, Is.EqualTo( newValue ) );
Whatever SubjectUnderTest does internally to achieve the desired effect, is not in the scope of the test. It's private to SubjectUnderTest, you don't care how it is done as long as it is done at all. When testing, look at the externally visible state of your subject under test, and what it does to its dependencies.
I am still learning Moq and am writing a unit test using Moq:
[TestMethod]
public void ProcessFileRowQueue()
{
var mock = new Mock<EdiEntityManager>();
mock.Setup(s => s.GetFileRowEntitiesToProcess()).Returns(GetMockFileRowEntities);
var controller = new EdiController("LOCAL", mock.Object);
controller.ProcessFileRowQueue();
}
This works.
Now, I want to ensure that the ensure ProcessFileRowQueue() actually did it's job. There is a method on EdiManager that I would like to mock so I can intercept the parameters and inspect them and ensure they are correct.
public virtual void SaveNewEdiDocument(EdiDocument ediDocument, Translation translation)...
However, I don't see how to mock a method with parameters.
This is what I thought it would be:
mock.Setup(s => s.SaveNewEdiDocument(It.IsAny<EdiDocument>(), It.IsAny<Translation>()).Returns(ValidateResults));
How do I write this, or is there a different way I should be verifying the results?
I found the Callback method:
[TestMethod]
public void ProcessFileRowQueue()
{
var mock = new Mock<EdiEntityManager>();
mock.Setup(s => s.GetFileRowEntitiesToProcess()).Returns(GetMockFileRowEntities);
mock.Setup(s => s.SaveNewEdiDocument(It.IsAny<EdiDocument>(), It.IsAny<Translation>()))
.Callback<EdiDocument, Translation>(VerifyResult);
var controller = new EdiController("LOCAL", mock.Object);
controller.ProcessFileRowQueue();
}
public void VerifyResult(EdiDocument ediDocument, Translation translation)
{
}
I have a method like this:
public int InsertOrUpdateCustomer(Customer customer)
{
var result = default(int);
try
{
using (var customerContext = new Customer())
{
var customerResult = customerContext.UpdateGraph(coupon, map => map.OwnedCollection(p => p.CustomerPoints));
couponsContext.SaveChanges();
result = customerResult.CustomerTypeID;
}
}
catch (Exception ex)
{
// Log the Exception
}
return result;
}
It creates an instance of CustomerContext, Saves, and returns the new CustomerID.
I am trying to use Moq for this and have this method where the test needs to check for a integer value being returned.
[TestMethod]
public void Inserting_A_Customer_Should_Return_A_IntegerValue(Customer customer)
{
var mock = new Mock<ICustomerRepository>();
int customerId = 1;
mock.Setup(c => c.InsertOrUpdateCustomer(customer)).Returns(new Customer() { Id = customerId });
}
That gives this error:
cannot convert from 'Entities.Commerce.Customer' to 'System.Func<int>'
I am also new to Moq.
What I would like to know from this question is, if one has a code like above, how does one proceed with writing Unit Tests.
It would be of great help if some pointers are given in getting to know that process.
Thanks in advance.
The error itself is because the method you are setting up is of this signature:
public int InsertOrUpdateCustomer(Customer customer)
Whereas your setup is trying to return a customer
mock.Setup(c => c.InsertOrUpdateCustomer(customer))
.Returns(new Customer() { Id = customerId });
Changing this to return a fake int such as .Returns(42); will avoid the error.
The not so good news is if the purpose of the test is Inserting_A_Customer_Should_Return_A_IntegerValue that you will be mocking the very thing you are trying to test (you would just be testing Moq).
What you need to do is Moq out your DbContext, which makes this line problematic, given its tight coupling:
using (var customerContext = new CustomerContext())
The suggestion here is to either allow the DbContext to be injected into the constructor of your class you are testing (or inject a factory interface which can create a DbContext).
You can then Mock the DbContext and the relevant IDbSets (Customers) as per this MSDN article here, which you can then inject into your class being tested, and test any logic / branching in your class.
I have a test where I pass in an object like so:
var repo = new ActualRepo();
var sut = new Sut(repo);
In my test, Repo has one method that I need to actually execute, whilst another method I want to mock out and not execute.
So for example, take this pseudocode:
var repo = new Mock<IRepo>();
repo.Setup(m => m.MethodIWantToCall()).WillBeExecuted();
repo.Setup(m => m.MethodIWantToMock()).Returns(false);
Using Moq, is this possible and how can it be done?
EDIT:
I've used TypeMock in the past and you can do something like.
Isolator.When(() => repo.MethodToIgnore()).WillBeIgnored();
Isolator.When(() => repo.MethodToActuallyRun()).WillBeExecuted();
Not too sure from the question if this is useful but it is possible to partially mock an object if the method that you want to mock is virtual.
public class Foo {
public string GetLive() {
return "Hello";
}
public virtual string GetMock() {
return "Hello";
}
}
public class Snafu {
private Foo _foo;
public Snafu(Foo foo) {
_foo = foo;
}
public string GetMessage() {
return string.Format("{0} {1}", _foo.GetLive(), _foo.GetMock());
}
}
[TestMethod]
public void NotMocked() {
var snafu = new Snafu(new Foo());
Assert.AreEqual("Hello Hello", snafu.GetMessage());
}
[TestMethod]
public void Mocked() {
var mockFoo = new Mock<Foo>();
mockFoo.Setup(mk => mk.GetMock()).Returns("World");
var snafu = new Snafu(mockFoo.Object);
Assert.AreEqual("Hello World", snafu.GetMessage());
}
You can't do this with Moq if you use the same object unless one of the method is virtual and you are basing your mock on a type rather than an interface.
That's because when you are passing a mock object based on an interface, you aren't passing a real object so it does not have access to the real methods of the object.
You are passing a dynamic proxy which will respond to methods it has been setup to respond to.
I believe TypeMock rewrites the assemblies at runtime to achieve this, something Moq definitively doesn't do.
If you want to achieve similar results with Moq:
You could mock both methods
You would have to extract both methods to different dependencies so as to mock one dependency and not the other.
You could have the method you need mocked be virtual, which would be the solution I would prefer.
EDIT : I edited my answer for correctness after reading AlanT's answer.
I'm trying to mock out a call to a repository. I can successfully do so when a repository call returns a value by using Setup().Returns:
mock.Setup(m => m.Get(param)).Returns(new CustomObject());
However, when I try to do the same sort of Setup for repository calls which return no values, Moq throws an exception and tells me this method was never called i.e.Expected invocation on the mock exactly 1 times, but was 0 times
Precisely, I'm doing this:
mock.Setup(m => m.UpdateRepository(param1)); // UpdateRepository returns no value
service.DoUpdate(param1);
mock.Verify(m => m.UpdateRepository(param1), Times.Exactly(1));
Note: DoUpdate method only calls repository.UpdateRepository(param1);
Am I not using Moq setup correctly in this instance? Is there a different way to Setup methods which return no value?
Thanks in advance!
You don't need to setup the call to UpdateRepository. Just verify it.
Given these types:
public interface IRepository
{
void UpdateRepository(string value);
}
public class Service
{
public Service(IRepository repository)
{
_repository = repository;
}
public void DoUpdate(string value)
{
_repository.UpdateRepository(value);
}
private IRepository _repository;
}
Your test method could be as follows:
const string param1 = "whatever";
var repoMock = new Mock<IRepository>();
var sut = new Service(repoMock.Object);
sut.DoUpdate(param1);
repoMock.Verify(x => x.UpdateRepository(param1), Times.Once());
Try using Verifiable:
mock.Setup(m => m.UpdateRepository(param1)).Verifiable();