UNIT test dto and domain objects - unit-testing

I am planning to write an abstract class kind of thing for testing all my DTOs and DOMAIN objects. This class will take in templatable object (generic type)and use reflection to get the properties' types within and will assign some default values to the primitive types identified and later will assert these type values by accessing them. This way whenever my DTO tests inherit this class, most of the code is tested with one line of code written in the test. This is just an idea and want to know from you all if I am reinventing the wheel if something like this already exists? If there is a better way to test DTO's and domain object with less and resuable code.

I don't think that this is a good approach for testing Domain objects. By definition, these objects encapsulate data and related behavior, they suppose to be much more than just dumb data containers with getters and setters. You will have to hand write unit tests for these objects just like you hand-wrote the objects themselves. This is where you actually suppose to be spending time according to DDD.
Regarding DTOs you may want to look at this question.

My advice :
Don't unit test DTO's. These are just simple data structures with a bunch of getters and setters and no behavior. Getters and setters are too dumb to be tested (unless they encapsulate some kind of conditional logic which is rarely the case with DTO's).
Don't try to automate or genericize your domain object tests. I can't see how code that tests their behavior can be reused anyway since they all have a different behavior by definition.

Even though I think is kind of worthless to unit test DTOs, based on #Dmitry's answer I came up with this class:
[TestClass]
public class PeopleTest
{
[TestMethod]
public void OneObjectNull()
{
Person obj1 = null;
var obj2 = new Person
{
Id = "101",
Name = "George Waits",
Address = "Lake Palmer 10"
};
Assert.AreNotEqual(obj1, obj2);
Assert.AreNotEqual(obj2, obj1);
}
[TestMethod]
public void DeepEqual()
{
var obj1 = new Person
{
Id = "101",
Name = "George Waits",
Address = "Lake Palmer 10"
};
var peolpleList1 = new List<Person> { obj1 };
var peolpleList2 = new List<Person> { obj1 };
Assert.AreEqual(obj1, obj1);
CollectionAssert.AreEqual(peolpleList1, peolpleList2);
}
[TestMethod]
public void DeepNotEqual()
{
var obj1 = new Person
{
Id = "101",
Name = "George Waits",
Address = "Lake Palmer 10"
};
var obj2 = new Person
{
Id = "102",
Name = "Rachel Smith",
Address = "Lake Palmer 10"
};
var peolpleList1 = new List<Person> { obj1 };
var peolpleList2 = new List<Person> { obj2 };
Assert.AreNotEqual(peolpleList1, peolpleList2);
var group1 = new KeyValuePair<string, List<Person>>("group1", peolpleList1);
var group2 = new KeyValuePair<string, List<Person>>("group2", peolpleList2);
Assert.AreNotEqual(group1, group2);
}
[TestMethod]
public void PropertyPositive()
{
var obj1 = new Person
{
Id = "101",
Name = "George Waits",
Address = "Lake Palmer 10"
};
obj1.Address = "Parker av 101";
var obj2 = new Person
{
Id = "102",
Name = "Rachel Smith",
Address = "Lake Palmer 10"
};
obj1.Address = "Listener av 45";
Assert.AreNotEqual(obj1, obj2);
}
}

Related

unit test convert to dto extension method with fluentconversion

if i have a extension method that converts an Person object to a PersonDTO then
should i unit test that the conversion occurs correctly
if so and i use fluentassertions how do i assert that the conversion is correct
my extension method is:
public static PersonDTO ToDto (this Person person)
{
if (person == null) return null;
return new PersonDTO
{
FirstName = person.FirstName,
LastName = person.LastName,
Dob = person.Dob,
Identifier= person.Id
};
}
my person object has other properties that are not being mapped.
to get the personDTO object i would therefore do something similar to below:
var newPerson = new Person{ //set properties here };
var personDto = newPerson.ToDto();
First, yes, this code should be tested.
In order to check that the conversion is correct, you have to build the expected result manually, and then assert that the result of the function is the same:
var person = new Person{ ... };
var expectedPersonDto = new PersonDto{ ... };
person.ToDto().Should().BeEquivalentTo(expectedPersonDto);
See this for more information on comparing object graphs.

Why is it possible to reassign a List<T> property in Realm?

In Realm, it is required to name a List<T> property as let, like:
class Dog:Object {
dynamic name = "doggy"
let mate = List<Dog>()
}
let dog1 = Dog()
dog1.name = "Bark"
let dog2 = Dog()
dog2.name = "Brave"
dog1.mates.append(dog2)
As mates is a let variable. You can't reassign it by
let dog3 = Dog()
dog3.name = "Bright"
dog3.mates.append(dog2)
//dog1.mates = dog3.mates // Cannot assign to property: 'mates' is a 'let' constant
But you can reassign it by
dog1["mates"] = dog3.mates // works
dog1.setValue(dog3.mates, forKey: "mates") //works
My question is why "reassign a let variable" allows?
All model properties in Realm are mutable under the hood. However, generic properties don't generate objective-c getters and setters, and therefore can't be overridden, which is why List and RealmOptional properties in Realm must be defined as let, because if they were var and re-assigned via the native setter, Realm wouldn't know about and Bad Things would happen.
Since Realm can handle setValue(_:forKey:), that works.

Retrieve data from MockRepository?

I'm new to Unit Testing and I'm using Rhino Mock in ASP.NET MVC
I have created a main test class with this code :
[TestFixture]
public class PersistenceTest
{
[Test]
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
var mockDataSource = MockRepository.GenerateMock<IRepository<T>>();
mockDataSource.Add(entity);
var fromDb = mockDataSource.FindBy(entity.Id);
return fromDb;
}
}
and create a customer test class like this :
[TestFixture]
public class CustomerTests : PersistenceTest
{
[Test]
public void Can_Save_And_Load_Customer()
{
var customer = new Customer()
{
Id = 12,
Name = "Reza",
Family = "Pazooki",
Company = "Rozaneh",
Email = "ipazooki#gmail.com",
Mobile = "09352463668",
Fax = "021-44869059",
Tel = "021-44869059",
WebSite = "www.rozanehmedia.com"
};
var fromDb = SaveAndLoadEntity(customer);
fromDb.ShouldNotBeNull();
}
}
but when run the code, it says that return value from Database is NULL!!!
I don't know what is wrong with my code but I save and retrieve data from mock repository and it seems every thing is ok.
tnx form any help in forward :)
Mocks are used to record invocations on objects for further verification or to provide values when called (later behavior requires setup).
In your SaveAndLoadEntity method you make calls to mock (Add and FindBy). Since mock is a fake object with no real behavior, those calls do nothing (they don't save nor extract any entities to/from database).
If you want to test persistence layer you should be doing tests against real database instance (or optionally, in-memory one).
// [Test] attribute is not needed
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
var dataSource = new DataSource("connection string");
dataSource.Add(entity);
var fromDb = dataSource.FindBy(entity.Id);
return fromDb;
}
At the moment you are making calls to not-setup mock which doesn't achieve anything.
Thank you jimmy_keen.
I change my code according to your advice like this and it worked great :)
[TestFixture]
public class PersistenceTest
{
protected ISession Session;
protected ITransaction Transaction;
[SetUp]
public void SetUp()
{
var helper = new NHibernateHelper("...connectionString....");
Session = helper.SessionFactory.OpenSession();
Transaction = Session.BeginTransaction();
}
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
Session.Save(entity);
Transaction.Commit();
var fromDb = Session.Get<T>(entity.Id);
return fromDb;
}
}

Issues with mocking methods using Moq

I have the following class that has two static methods Retrieve and RetrieveWithQuery.
Below the classes listed here, I have included a snippet of the test.
All but the last assert of the test fails with the following message:
Failed TestMethod2 MoqTest Assert.AreEqual failed. Expected:. Actual:<(null)>.
I understand that the problem may be that the query that I setup in the mock
is a different instance from the query used in the RetrieveWithQuery method.
And that is why is would be returning null.
In a perfect world I would simply re-factor the service class, unfortunately I am
working with legacy code that is already production. The goal is to first complete
tests, then re-factor code and run regression testing before updating production
environment.
Is there a workaround or different way to test this?
public class MyService
{
public virtual string RetrieveMethod(string account)
{
if (account == "The abc company")
{
return "Peter Smith";
}
return "John Doe";
}
public virtual string RetrieveMethod(MyQuery query)
{
return RetrieveMethod(query.QueryString);
}
public static string Retrieve(MyService service, string value)
{
return service.RetrieveMethod(value);
}
public static string RetrieveWithQuery(MyService service, string value)
{
var query = new MyQuery
{
QueryString = value
};
return service.RetrieveMethod(query);
}
}
public class MyQuery
{
public string QueryString;
}
[TestMethod]
public void TestMethod2()
{
var mockService = new Mock<MyService>();
const string company = "The abc company";
const string expectedContact = "Peter Smith";
var queryAccount = new MyQuery
{
QueryString = company
};
// Setup base retrieve
mockService.Setup(myServ => myServ.RetrieveMethod(company)).Returns(expectedContact);
// Setup base retrieve with query
mockService.Setup(myServ => myServ.RetrieveMethod(queryAccount)).Returns(expectedContact);
// test base retrieve with query - PASS
Assert.AreEqual(expectedContact, mockService.Object.RetrieveMethod(queryAccount));
// test static method retrieve - PASS
Assert.AreEqual(expectedContact, MyService.Retrieve(mockService.Object, company));
// test static method retrieve with query - FAIL
Assert.AreEqual(expectedContact, MyService.RetrieveWithQuery(mockService.Object, company));
}
Try this for your setup:
// Setup base retrieve with query
mockService.Setup(myServ => myServ.RetrieveMethod(It.Is<Query>(q=>q.QueryString == queryAccount.QueryString)).Returns(expectedContact);
Or you could overload on Equals for Query so that the Query that gets created is equal to expectedQuery.
The Moq QuickStart page has good examples of this and more which should help a lot.

Faking an nHibernate session with FakeItEasy

I would like to inject a fake nHibernate session into my repository using FakeItEasy, then return a list of objects that are predefined within my test. Does anyone have experience doing this?
Here is the example test:
[TestFixture]
public class ProductionRepositoryTester
{
private ProductionRepository _productionRepository;
[SetUp]
public void SetupFixture()
{
const string propertyNumber = "123";
Tank tank = new Tank { PropertyNumber = propertyNumber };
var session = A.Fake<ISession>();
var sessionFactory = A.Fake<ISessionFactory>();
A.CallTo(session).WithReturnType<IList<Tank>>().Returns(new List<Tank> { tank });
_productionRepository = new ProductionRepository(session, sessionFactory);
}
[Test]
public void ProductionRepositoryCanGetTanks()
{
var tanks = _productionRepository.GetTanks();
Assert.AreNotEqual(0, tanks.Count(), "Tanks should have been returned.");
}
}
And here is the call within the actual ProductionRepository class:
public IEnumerable<Tank> GetTanks()
{
var tanks = Session.CreateCriteria(typeof(Tank)).List<Tank>();
return tanks;
}
Thanks in advance for any advice!
First of all I would advice against faking the NHibernate interfaces at all, this is (in my opinion) too low a level to unit test. It's probably better to have some integration tests for these scenarios. In other words, unit test all interaction with an abstraction for ProductionRepository (IProductionRepository) but stop there. Now, however, that's just my opinion and if you really want to do this I think you would have to change your fake-setup:
The session returns a criteria, not ever a IList directly. Therefore you'd have to have a fake criteria too:
var fakeCriteria = A.Fake<ICriteria>();
A.CallTo(fakeCriteria).WithReturnType<IList<Tank>>().Returns(new List<Tank> { tank });
A.CallTo(session).WithReturnType<ICriteria>().Returns(fakeCriteria);
(I hope I remember the criteria type correctly, I think it's ICriteria but I'm not a hundred percent sure.)