In the example below, I'm attempting to test that the notes text is changed. Is the Assert.AreEqual(note.Text, text); correct?
[TestMethod()]
public void CreateNoteTest_Pass()
{
HomeController target = new HomeController(); // TODO: Initialize to an appropriate value
var note = new NotePM();
string text = "This is my test note" + DateTime.Now;
note.Text = text;
int id = note.NoteId;
note.CreatedByUserName = Membership.GetUser("danielle").UserName;
ActionResult actual;
actual = target.Create(note);
Assert.AreNotEqual(id, note.NoteId);
Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
Assert.AreEqual(note.Text, text);
}
Here's one take on this:
[TestMethod()]
public void EnsureCreateNoteChangesNoteText()
{
string text = "This is my test note" + DateTime.Now;
var note = new NotePM()
{
Text = text;
CreatedByUserName = "danielle";
};
int id = note.NoteId;
ActionResult actual;
HomeController target = new HomeController();
actual = target.Create(note);
Assert.AreNotEqual(id, note.NoteId, "note.NoteID must be assigned by the controller");
Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
Assert.AreNotEqual(text, note.Text, "note.Text must be changed by the controller");
}
Assert.AreNotEqual() is used to check for inequality (and there is a string overload which does a value comparison)
With the asserts which take 2 values, these should be Assert.xxx(Expected, Actual) otherwise the failure message is inverted.
Unit tests should isolate the system under test as far as possible (HomeController in this example). If HomeController is dependent on asp.net Membership ideally, you should inject this to the controller in the constructor to ensure it can be mocked. This way you can ensure that the unit test runs without the need to prep database data, setup connections from the Unit Test runner, etc.
Related
I have a mocked class with a property that has a get and set. My code under test calls the setter to assign a connection string value. My test code mocks the class that contains the property and I add MustBeCalled when I arrange the mock.
ViewModel Code:
public class ClientViewModel
{
private readonly IMgmtDataProvider dataProvider;
public ClientViewModel(IMgmtDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
private string clientConnectionString;
public string ClientConnectionString
{
get { return clientConnectionString; }
set
{
clientConnectionString = value;
if (dataProvider != null)
dataProvider.ClientConnectionString = value;
}
}
}
Test Code:
//Arrange
const string connectionString = "THIS IS MY CONNECTIONSTRING";
var mockedDataProvider = Mock.Create<IMgmtDataProvider>();
Mock.Arrange(() => mockedDataProvider.ClientConnectionString).MustBeCalled();
//Act
var testViewModel = new ClientViewModel(mockedDataProvider);
testViewModel.ClientConnectionString = connectionString;
//Assert
var callCount = Mock.GetTimesCalled(() => mockedDataProvider.ClientConnectinString);
Assert.IsTrue(callCount > 0);
my Mock.Arrange(...).MustBeCalled(); appears to be applied to the getter, not the setter. So, when I call Mock.GetTimesCalled(...), it returns 0. I need to apply the MustBeCalled to the setter instead of the getter. I want to assure the dataprovider's connectionstring is getting set when the viewmodel's connection string gets set. How do I tell JustMock to track how many times a mocked setter is called?
Setters are arranged using the Mock.ArrangeSet() method, like so:
Mock.ArrangeSet(() => mockedDataProvider.ClientConnectionString = Arg.AnyString).MustBeCalled();
....
Mock.Assert(mockedDataProvider); // assert all expectations on this mock
You can also use Mock.AssertSet() as an alternative to the ArrangeSet().MustBeCalled() combo.
And finally, there's the Mock.GetTimesSetCalled() method for getting the number of times that a setter was called.
Check out the documentation on property mocking for examples.
The application that I'm testing is a simple app where notes are displayed for the user that created them. I found a bug where if you edit the note it is removed from the users list of notes. I'm trying to create a unit test that shows this by editing the note and then doing a count on the total notes. I'm not sure how to do the count on an assert. Here's what I have:
[TestMethod()]
public void Edit_Note_Pass()
{
HomeController target = new HomeController();
var note = new NotePM();
string text = "Note 1 Danielle " + DateTime.Now;
note.Text = text;
int id = note.NoteId;
note.CreatedByUserName = Membership.GetUser("danielle").UserName;
ActionResult actual;
note.Text = text;
actual = target.Create(note);
actual = target.Edit(note.NoteId);
Assert.IsInstanceOfType(actual, typeof(ViewResult));
Assert.AreEqual(note.Text, text);
}
In the below example of a unit test, the test is attempting to validate the note is created. Shouldn't the Assert be an "Assert.AreEqual" to verify if the id's match?
[TestMethod()]
public void CreateNoteTest_Pass()
{
HomeController target = new HomeController(); // TODO: Initialize to an appropriate value
var note = new NotePM();
note.Text = "This is my test note" + DateTime.Now;
int id = note.NoteId;
note.CreatedByUserName = Membership.GetUser("danielle").UserName;
ActionResult actual;
actual = target.Create(note);
Assert.AreNotEqual(id, note.NoteId);
Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
I'm curious to know what the
target.create(note)
method does. It looks like it takes a NotePM instance and does some work on it (create it in the DB and get the ID, for example).
My guess is that this test is verifying that target.create actually altered note.ID. So it saves the value of note.ID in the variable id, then calls create(note) and asserts that the value of the ID actually changed to some new value.
Do you want to compare note and actual and verify that they are equal ?
If so, use AreEqual...
Ex:
Assert.AreEqual(note, actual, "Note's are not equal.");
How do I set up my test method on that mocks a repository which accepts an object?
This is what I have so far:
Service.cs
public int AddCountry(string countryName)
{
Country country = new Country();
country.CountryName = countryName;
return geographicsRepository.SaveCountry(country).CountryId;
}
test.cs
[Test]
public void Insert_Country()
{
//Setup
var geographicsRepository = new Mock<IGeographicRepository>();
geographicsRepository.Setup(x => x.SaveCountry(It.Is<Country>(c => c.CountryName == "Jamaica"))); //How do I return a 1 here?
GeographicService geoService = new GeographicService(geographicsRepository.Object);
int id = geoService.AddCountry("Jamaica");
Assert.AreEqual(1, id);
}
SaveCountry(Country country); returns an int.
I need to do 2 things:
First test, I need to tell the setup to return an int of 1.
I need to create a second test Insert_Duplicate_Country_Throws_Exception(). In my Setup, how do I tell the repository to throw an error when I do:
int id = geoService.AddCountry("Jamaica");
int id = geoService.AddCountry("Jamaica");
Framework:
NUnit.
Moq.
ASP.NET MVC - repository pattern.
Your first test should look something like this:
[Test]
public void Insert_Country()
{
Mock<IGeographicRepository> geographicsRepository = new Mock<IGeographicRepository>();
GeographicService geoService = new GeographicService(geographicsRepository.Object);
// Setup Mock
geographicsRepository
.Setup(x => x.SaveCountry(It.IsAny<Country>()))
.Returns(1);
var id = geoService.AddCountry("Jamaica");
Assert.IsInstanceOf<Int32>(id);
Assert.AreEqual(1, id);
geographicsRepository.VerifyAll();
}
The second test should look like this:
[Test]
public void Insert_Duplicate_Country_Throws_Exception()
{
Mock<IGeographicRepository> geographicsRepository = new Mock<IGeographicRepository>();
GeographicService geoService = new GeographicService(geographicsRepository.Object);
// Setup Mock
geographicsRepository
.Setup(x => x.SaveCountry(It.IsAny<Country>()))
.Throws(new MyException());
try
{
var id = geoService.AddCountry("Jamaica");
Assert.Fail("Exception not thrown");
}
catch (MyException)
{
geographicsRepository.VerifyAll();
}
}
I think maybe you are slightly misunderstanding the purpose of testing with mocks in the two scenarios you have supplied.
In the first scenario, you wish to test that 1 is returned when you pass in "Jamaica". This is not a mock test case but a test case for real behaviour as you wish to test a specific input against an expected output i.e. "Jamaica" -> 1. In this situation mocking is more useful to ensure that internally your service calls SaveCountry on the repository with the expected country, and that it returns the value from the call.
Setting up your "SaveCountry" case and then calling "VerifyAll" on your mock is the key. This will assert that "SaveCountry" was indeed called with country "Jamaica", and that the expected value is returned. In this way you have confidence that your service is wired up to your repository as expected.
[Test]
public void adding_country_saves_country()
{
const int ExpectedCountryId = 666;
var mockRepository = new Mock<IGeographicRepository>();
mockRepository.
Setup(x => x.SaveCountry(It.Is<Country>(c => c.CountryName == "Jamaica"))).
Returns(ExpectedCountryId);
GeographicService service= new GeographicService(mockRepository.Object);
int id = service.AddCountry(new Country("Jamaica"));
mockRepo.VerifyAll();
Assert.AreEqual(ExpectedCountryId, id, "Expected country id.");
}
In the second scenario you wish to test that an exception is raised when you attempt to add a duplicate country. There's not much point in doing this with a mock as all you will test is that your mock has behaviour when adding duplicates, not your real implementation.
Another day , another question. My service layer has the following method
public MatchViewData CreateMatch(string user)
{
var matchViewData = !HasReachedMaxNumberOfMatchesLimit(user) ?
CreateMatchAndAddToRepository(user) :
MatchViewData.NewInstance(new Match(user));
matchViewData.LimitReached = HasReachedMaxNumberOfMatchesLimit(user);
return matchViewData;
}
The method calls the this helper method to create a new match object:
private MatchViewData CreateMatchAndAddToRepository(string user)
{
var match = new Match(user);
MatchRepository.Add(match);
return MatchViewData.NewInstance(match);
}
The repository stores the given match object and sets the id to some value > 0.
public void Add(Match match)
{
Check.Require(match != null);
var numberOfMatchesBefore = Matches.Count;
SetIdPerReflection(match, NextVal());
Matches.Add(match);
Check.Ensure(numberOfMatchesBefore == Matches.Count - 1);
}
The matchviewdata object copies some properties of the the match object (including the id).
My unit test should verify that the resulting viewdata object in the service has an id > 0. To archieve this, i have to mock the repository and the behaviour of the add method. But the service method creates a new match object every time its been called and the add method on the repository updates the referenced match object (there is no need for a return value). I have no idea to solve this with moq.
This is my unit test so far:
[Test]
public void ServiceCreateMatchReturnedMatchViewDataHasNonZeroId()
{
var match = TestUtils.FakePersistentMatch(User, 1);
var repositoryMock = new Mock<IMatchRepository>();
repositoryMock.Setup(
r => r.Add(It.IsAny<Match>())).Callback(() => match.Id = 1);
var serviceFacade = new DefaultServiceFacade(repositoryMock.Object);
var returnedMatch = serviceFacade.CreateMatch(User);
Assert.That(returnedMatch.Id, Is.GreaterThan(0));
}
I tried some other variations - nothing works.
It looks to me your problem is in this line;
repositoryMock.Setup(
r => r.Add(It.IsAny<Match>())).Callback(() => match.Id = 1);
What you're actually doing here is setting the id of the first match object you have declared in your test, NOT the new match created in your service.
Because the Match object you will be supplying to the Repository is created internally, I can't think of an easy way to reference it in your Test method to setup a callback for it. To me, this is a sign you may be trying to test too much in one unit test.
I think you should simply test that the Add method is called and write a separate test to ensure that it works as exepected.
I propose something like this;
[Test]
public void ServiceAddsNewMatchToRepository()
{
var repositoryMock = new Mock<IMatchRepository>();
bool addCalled = false;
repositoryMock
.Expect(r => r.Add(It.Is<Match>(x => x.Id == 0))
.Callback(() => addCalled = true);
var serviceFacade = new DefaultServiceFacade(repositoryMock.Object);
serviceFacade.CreateMatch(User);
Assert.True(addCalled);
}
....
[Test]
public void AddingANewMatchGeneratesANewId()
{
var match = new Match(user);
var matchRepository = new MatchRepository();
var returnedMatch = matchRepository.Add(match);
Assert.That(returnedMatch.Id, Is.GreaterThan(0));
}