Testing Remove method without a call to Add method - c#

I am writing test for a class thats manage trees of Tag objects:
public class Tag
{
public virtual int Id { get; set; }
public virtual string Description{ get; set; }
private IList<Tag> children = new List<Tag>();
public virtual IEnumerable<Tag> Children
{
get {return children .ToArray();}
}
public void AddChildTag(Tag child)
{
children.Add(child);
}
public void RemoveChildTag(Tag child)
{
children.Remove(child);
}
}
As you can see the only mode to set the parent property is via the AddChildTag method and this is exactly what i want, my problem is in unit test: since every test should be atomic, how can i test the RemoveChildTag method?
Only way i see is a call to the add method and later to the remove, but in this way if Add as some errors, even the test of remove will fail, so atomicity is lost.
How can that be done?
EDIT
I removed parent property from Tag object, since i no more use it
Some test according to solution using NUnit and FluentAssertion
[Test]
public void AddChildTagAddsChildren()
{
//Arrange
Tag parent = new Tag();
Tag child = new Tag();
//Act
parent.AddChildTag(child);
//Assert
parent.Children.Should().Contain(child);
}
[Test]
public void RemoveChildTagRemovesAddedChildren()
{
//Arrange
Tag parent = new Tag();
Tag child = new Tag();
parent.AddChildTag(child);
//Act
parent.RemoveChildTag(child);
//Assert
parent.Children.Should().NotContain(child);
}
[Test]
public void RemoveChildTagThrowsNothingWhenNoChild()
{
//Arrange
Tag parent= new Tag();
Tag child= new Tag();
//Act
Action RemoveChild = () => parent.RemoveChildTag(child);
//Assert
RemoveChild.ShouldNotThrow();
}

Your unit tests should reflect actual use cases of your class. How will your consumers use RemoveChildTag method? Which makes more sense? Which is how you'd use collection of objects?
var parent = new Tag();
// later
parent.RemoveChildTag(child);
… or
var parent = new Tag();
parent.AddChildTag(child);
// later
parent.RemoveChildTag(child);
Your consumers will remove objects they previously added. This is your use case, "Remove removes elements previously added" (note that it also produces excellent test method name).
Add and Remove methods are often complementary - you can't test one without the other.

There are some ways to test Remove method:
Mocking - mock your data structure, and call remove , so you can test calling the right methods
Inheritance - make children protected. Your test class will inherit from Tag class. Now you can init children member so we can test the remove
Use Add Method
I think option 3 is the best, it's ok using other methods in your unit testing, if Add have some error , more then 1 test will fail - you should be able to understand what you need to fix.
Also, each unit test should test some basic behavior, even if you need to do some preparation before.
If those preparation failed, fail the test with the relevant comments
Option 1 - is best when you code is reaching to 3rd party - other server, file system & more. Since you don't want to make those calls in unit test - mock the response.
Option 2 - best I can say , is when you want to test protected / private method, without needing to make all the calls "on the way" that your code does (public method that make many calls that eventually call the method you want to test), since you want to test only a specific logic. It also easy to use this option when your class have some state that you want to test, without needing to write a lot of code to bring your class to this state.

You could use an PrivateObject Class to Arrange your object under test
Allows test code to call methods and properties on the code under test
that would be inaccessible because they are not public.
EDIT
then you could get full access to wrapped object by PrivateObject.RealType and PrivateObject.Target Properties
EDIT
Anyway, every system which break the segregation and encapsulation of a class make useless the black box approach of Unit Testing in TDD and should be avoided as a poison :)

A common approach to unit testing is the Arrange-Act-Assert paradigm.
I would personally have two tests for the remove method, one which is removing a child which was never added, what should happen? Should an exception be thrown?
This would look like:
[Test]
public void RemoveChildTagThrowsExceptionWhenNoChildren()
{
// Arrange
var tag = new Tag();
var tagToRemove = new Tag();
// Act & Assert
Expect(() => tag.RemoveChildTag(tagToRemove), Throws.ArgumentException);
}
Then I would have another test for what should happen when an added child is removed:
[Test]
public void RemoveChildTagRemovesPreviouslyAddedChild()
{
// Arrange
var tag = new Tag();
var childTag = new Tag();
tag.AddChildTag(childTag);
// Act
tag.RemoveChildTag(childTag);
// Assert
Expect(tag.Children.Contains(childTag), Is.False);
}
It may be of interest to note that quite a lot of .NET Remove implementations return a bool result which indicates whether any removal was actually performed. See here.

Related

Mocking a method to assign value to field in Model C# Moq

I need to add a method to a model that given some parameters assigns a value to one of the model's fields.
public class ModelName: SomeModel<ModelName>, IModelName
{
[Field]
public string SomeField{ get; set; }
[Field]
public string FieldSetByMethod{ get; set; }
public new async Task MethodToSetField(string parameter)
{
var someClassInstance = new SomeExternalClass(parameter);
FieldSetByMethod = someClassInstance(parameter).method();
}
}
Now when I'm writing unit tests and I want to have a way of checking that this MethodToSetField was called. However, I can't really actually call the MethodToSetField method as creating SomeExternalClass is not desirable (e.g. because it creates unique ID).
I don't really have experience with neither C# nor Moq. How can I mock this function so it behaves more or less like this:
ModelNameInstance.Setup(c => c.MethodToSetField("Parameter")).Assigns(FieldSetByMethod,"DummyValue");
Or maybe I can somehow restructure the code / write tests in a way to imitate this behavior?
You could inject ISomeExternalClass into this class and then mock it, and test against the mock, or if you can't do that - inject ISomeExternalClassFactory into this class and then mock it. ISomeExternalClassFactory mock would return a mock of ISomeExternalClass that you could setup and test against.

How can I unit test, that one viewmodel sends to another viewmodel proper string?

In a view model's constructor I have a command declaration that calls a method:
OpenGroupCommand = new DelegateCommand(OnOpenGroupExecute);
And the method looks like:
private void OnOpenGroupExecute(object obj)
{
string groupName = (string)obj;
Application.Current.MainPage.Navigation.PushAsync(new GroupPage(groupName));
}
How can I test, that groupName is passed to another view model correctly? In another view model groupName parameter is sent to GroupName property on VM instance:
public class GroupPageViewModel : ViewModelBase, IGroupPageViewModel
{
private string _groupName;
public GroupPageViewModel(string groupName)
{
LoadGroupName(groupName);
}
public void LoadGroupName(string groupName)
{
GroupName = groupName;
}
public string GroupName
{
get
{
return _groupName;
}
set
{
_groupName = value;
OnPropertyChanged();
}
}
}
On debug all works fine, but how can I unit test it? Where can I read a bit about testing and mocking stuff like this, even with Moq framework?
I believe your question is actually about how to test navigation between pages.
In the implementation of method OnOpenGroupExecute, because you are using Xamarin forms stuff to implement the navigation, you have to refer Xamarin Forms assemblies in your test project which makes the unit test depend on Xamarin Forms.
As suggested in this document https://learn.microsoft.com/en-us/xamarin/xamarin-forms/enterprise-application-patterns/ , try to create an interface for navigation and navigate with viewmodel (more details on https://github.com/dotnet-architecture/eShopOnContainers)
And in your unit test project, implement a fake navigation service class like below and inject into the DI container:
public class FakeNavigationService : INavigationService //this interface is from MS eShopOnContainer project
{
private List<ViewModelBase> _viewModels = new List<ViewModel>();
public Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase {
//create viewModel object from DI container
//var viewModel = ......
_viewModels.Add(viewModel);
}
public ViewModelBase CurrentPageViewModel {
get {
if (_viewModels.Count() < 1) {
return null;
}
return _viewModels[_viewModels.Count() - 1];
}
}
}
This is just a suggestion. If you have implemented most of features in your app, it takes time to change navigate-with-page to navigate-with-viewmodel.
Well, let's see what you have:
you have some code in a private method, unless you make that public you won't be able to test it directly, because you can't call it. I am not considering here any tricks that allow you to call private methods.
what does that method do? It is not clear at all, it receives an object, we don't know what's in it. You're converting it to string, but what if it is not a string? Can you convert that object to a string? who knows.
So we have a method, that we don't know what it does, we don't know what it receives as parameters, we can't call it directly, but we want to test it. This is not a good position to be in.
Step back a bit and ask yourself, what are you really trying to test?
You said : How can I test, that groupName is passed to another view model correctly?
what does "correctly" mean? You need to define what it means for that string to be correct. This will give a test scenario you can work with.
I expect to receive an object, which looks like A and I want to convert it to a string which looks like B. Forget about viewmodels for now, that's just unimportant noise.
You can change the method into a public one and you can test that for different types of input data, you're getting the right result. This is literally, working with an object and extract some stuff from it. When that method is correct, you can guarantee that the viewmodel will receive the right input and that is good enough from a unit testing point of view.
You can of course add more tests for various inputs, you can test for correct failure conditions etc.

Frozen mock's property is getting overwritten

I'm having an issue where AutoFixture seems to be overwriting a property on a frozen mock. The property on the mocked class is read-only, and from what I've read, AutoFixture shouldn't be trying to do anything with it.
I've included code to reproduce the issue in LINQPad below. Victim is a trivial test class with two read-only properties. At issue is that once I have set the expectation for the Things property and registered the mock's Object as the instance for AutoFixture to return for the Victim type, the collection Things contains different strings.
To reproduce the problem, run the code below in LINQPad as a C# Program and reference AutoFixture and Moq from NuGet. Be sure to include the namespaces Moq and Ploeh.AutoFixture.
My expectation is that I should get back the object I registered with Register and that the collection Things in the returned Victim should return the collection I referenced in my call to SetupGet.
public class Victim
{
private string _vic;
private IEnumerable<string> _things;
public virtual string VictimName { get { return _vic; } }
public virtual IEnumerable<string> Things { get { return _things; } }
}
void Main()
{
var fixture = new Fixture();
var victimName = fixture.CreateAnonymous("VIC_");
var things = fixture.CreateMany<string>();
victimName.Dump("Generated vic name");
things.Dump("Generated things");
var victimMock = fixture.Freeze<Mock<Victim>>();
victimMock.SetupGet(x => x.VictimName).Returns(victimName).Verifiable();
victimMock.SetupGet(x => x.Things).Returns(things).Verifiable();
fixture.Register(() => victimMock.Object);
var victim = fixture.CreateAnonymous<Victim>();
(victim.Equals(victimMock.Object)).Dump("Victims are the same?");
victim.VictimName.Dump("Returned name");
victim.Things.Dump("Returned things");
(things.Equals(victim.Things)).Dump("Returned things are the same?");
victimMock.Verify();
}
My guess is that the Iterator for Things is actually the same, but that the strings it generates are different. This is actually by design, although we've later come to realize that this wasn't a particularly good design decision.
In AutoFixture 3, this behavior has been changed.
If I've guessed correctly, this issue will go away in AutoFixture 3. In AutoFixture 2 you should be able to resolve it by creating the fixture like this:
var fixture = new Fixture().Customize(new StableMultipeCustomization());

Methods for Adding Data to Mock DBs in C# Unit Tests

This post is meant to be more a discussion-starter, as I am somewhat new to unit testing and TDD.
I am currently writing some unit tests for a .NET process that interacts with several databases, and am using mock database contexts in an attempt to cover different edge cases within my tests, verify exception handling in the program itself, among other things. That being said, some of my unit tests use valid data, while others do not.
I am looking for feedback in terms of suggested best practices when adding valid/fake data to your mock database contexts. I've seen people do this a number of ways (e.g. - implement repository pattern, adding mock data to .csv files and making them part of the project, etc...).
I'm currently thinking about using a repository pattern for adding Survey objects to the Surveys table in my target DB.
First off, I've got the interface:
public interface ISurveyRepository
{
IQueryable<Survey> SurveySeries { get; }
}
This is implemented both for the mocking fake/valid data repositories as needed by unit tests
class FakeSurveyRepository : ISurveyRepository
{
private static IQueryable<Survey> fakeSurveySeries = new List<Survey> {
new Survey { id = 1, SurveyName="NotValid1", SurveyData="<data>fake</data>"},
new Survey { id = 2, SurveyName="NotValid2", SurveyData="<data>super fake</data>"},
.........,
new Survey {id = 10, SurveyName="NotValid10", SurveyData="<data>the fakest</data>" }
}.AsQueryable();
public IQueryable<Survey> SurveySeries
{
get { return fakeSurveySeries; }
}
}
// RealSurveyRepository : ISurveyRepository is similar to this, but with "good" data
I then have a class to consume this data for either fake/valid data by being passed a reference to the series in the constructor:
public class SurveySeriesProcessor
{
private ISurveyRepository surveyRepository;
public SurveySeriesProcessor( ISurveyRepository surveyRepository )
{
this.surveyRepository = surveyRepository;
}
public IQueryable<Survey> GetSurveys()
{
return surveyRepository.SurveySeries
}
}
And can then approach using these objects in my tests such as:
[TestClass]
public class SurveyTests
{
[TestMethod]
WhenInvalidSurveysFound_SurveyCopierThrowsInvalidSurveyDataErrorForEach()
{
// create mocking DB context and add fake data
var contextFactory = new ContextFactory( ContextType.Mocking );
var surveySeriesProcessor = new SurveySeriesProcessor( new FakeSurveyRepository() );
foreach(Survey surveyRecord in surveySeriesProcessor.GetSurveys() )
{
contextFactory.TargetDBContext.Surveys.AddObject( surveyRecord );
}
// instantiate object being tested and run it against fake test data
var testSurveyCopier = new SurveyCopier( contextFactory );
testSurveyCopier.Start();
// test behavior
List<ErrorMessage> errors = testSurveyCopier.ErrorMessages;
errors.Count.ShouldEqual( surveySeriesProcessor.GetSurveys().Count );
foreach(ErrorMessage errMsg in errors)
{
errMsg.ErrorCode.ShouldEqual(ErrorMessage.ErrorMessageCode.InvalidSurveyData);
}
}
}
NOTE: I realize that in the example code provided I don't necessarily need to make the classes implementing ISurveyRepository return the series as an IQueryable<Survey> (they could very well be List<Survey>). However, I am going to extend the functionality of the interface and these classes in the future to filter out the fake/valid series based on certain criteria added to LINQ queries, which is why I made the repositories implement IQueryable<>. This is mock-up code designed to convey the basic principles of what I'm thinking.
With all of this in mind, what I'm asking is:
Do you have any suggestions in terms of alternative approaches I could take in such scenarios?
What methods have you employed in the past, what did you like/not like about them? Which have you found were the easiest to maintain?
Given what I've posted, do you notice flaws in my general approach to unit testing? Sometimes I feel as though I write unit tests that attempt to cover too much ground instead of being concise, elegant, and to-the-point.
This is meant to be somewhat of an open discussion. Please keep in mind, this is the first set of unit tests I've ever written (I've read a decent amount of literature on the subject, however).
I think you're on a good track.
Personally, in the same situation, if I were dealing with a repository style pattern,
public interface IRepository<T>
{
IEnumerable<T> GetAll();
}
public class PonyRepository : IRepository<Pony>
{
IEnumerable<Pony> GetAll();
}
To actually supply me the data I need, I generally create a TestObjects or TestFakes class to supply the required data on-demand.
public class FakeStuff
{
public static IEnumerable<Pony> JustSomeGenericPonies(int numberOfPonies)
{
// return just some basic list
return new List<Pony>{new Pony{Colour = "Brown", Awesomeness = AwesomenessLevel.Max}};
// or could equally just go bananas in here and do stuff like...
var lOfP = new List<Pony>();
for(int i = 0; i < numberOfPonies; i++)
{
var p = new Pony();
if(i % 2 == 0)
{
p.Colour = "Gray";
}
else
{
p.Colour = "Orange";
}
lOfP.Add(p);
}
return lOfP;
}
}
And test with this as such:
[Test]
public void Hello_I_Want_to_test_ponies()
{
Mock<IRepository<Pony> _mockPonyRepo = new Mock<IRepository<Pony>>();
_mockPonyRepo.SetUp(m => m.GetAll()).Returns(FakeStuff.JustSomeGenericPonies(50));
// Do things that test using the repository
}
So this delivers reusability of the fake data, by keeping it out of the repository and in a place of it's own, meaning I can call this list of ponies anywhere a test requires a list of ponies, not just where a repository is involved.
If I need specific data for a specific testcase, i'll implement something like you had, but be a bit more explicit about what that particular Fake repository is for:
public class FakePonyRepositoryThatOnlyReturnsBrownPonies : IRepository<Pony>
{
private List<Pony> _verySpecificAndNotReusableListOfOnlyBrownPonies = new List....
public IEnumerable<Pony> GetAll()
{
return _verySpecificAndNotReusableListOfOnlyBrownPonies;
}
}
public class FakePonyRepositoryThatThrowsExceptionFromGetAll : IRepository<Pony>
{
public IEnumerable<Pony> GetAll()
{
throw new OmgNoPoniesException();
}
}
You mentioned CSV files as well - this could be viable (have used XML in the past), but I'd argue that holding fake data in a CSV or XML is just a worse version of keeping data in a localised DB using SQL CE or some equivalent. However, both of those are less maintainable and, crucially, in terms of unit tests, slower than using in-memory fake objects. I personally wouldn't use a file-based approach anymore unless I was specifically testing serialization or IO or something.
Hope there's something useful among all that lot...

Testing Entity Framework Data by Hitting the Database

I am trying to test my real data by actually hitting the database. I am actually testing my Repository classes. Here is an example of what I am doing;
/// <summary>
/// Summary description for Country
/// </summary>
[TestClass]
public class Country {
public Country() {
_countryRepo = new CountryRepository();
}
private ICountryRepository _countryRepo;
[TestMethod]
public void db_should_return_at_least_one_country_as_approved_all() {
//Act
var model = _countryRepo.GetAll();
//Assert
Assert.IsTrue(model.Count() >= 1);
}
[TestMethod]
public void db_should_return_at_least_one_country_as_approved_true() {
//Act
var model = _countryRepo.GetAll(ApprovalStatus.Approved);
//Assert
Assert.IsTrue(model.Count() >= 1);
}
[TestMethod]
public void db_should_return_Turkey_as_country_name_by_id() {
//Act
var model = _countryRepo.GetSingle(1000);
//Assert
Assert.AreEqual<string>("Turkey", model.CountryName);
}
[TestMethod]
public void db_should_return_Turkey_as_country_name_by_countryISO3166Code() {
//Act
var model = _countryRepo.GetSingle("TR");
//Assert
Assert.AreEqual<string>("Turkey", model.CountryName);
}
[TestMethod]
public void db_should_return_Turkey_as_country_name_by_GUID() {
//Act
var model = _countryRepo.GetSingle(Guid.Parse("9AF174A6-D0F7-4393-AAAD-B168BADEDB30"));
//Assert
Assert.AreEqual<string>("Turkey", model.CountryName);
}
}
This works pretty well for my needs but wondering if I am doing it right by the book. Is there any other patterns that I really should be following here. I do not want to fake my data, my real intense here is to test my DAL and real production data.
Your tests will fail if someone else (or even you) go to your database and create a new approved country or change your country name. You are going to think: "WTH is wrong with my repository, why is it not working as expected?" But yeah, the problem isn't with the repository.
When I write tests that hit the database I like to create the DB and load default values at startup and destroy then all right after that. I'm not sure if this is the best alternative, but it works pretty well. The problem with this approach is that it's slower and there is more to code.
For the requirement at hand, i.e. data that is really static, and should not be tampered with, I'd say this is a valid approach.
I would recommend to write data-driven tests however, instead of repeating the same test case for each country.
You should use static database just for testing and your methods testing GetAll should assert against real expected count. How do you know that it really returned what you expected if you just assert that it returned at least one record? You should even go through result set and test that all records satisfy the condition (but it is usually used for more complicated conditions).

Categories

Resources