Am I setting up these tests correctly?

4 posts, 0 answers
  1. Graham
    Graham avatar
    4 posts
    Member since:
    May 2011

    Posted 13 May 2011 Link to this post

    I am attempting to use JustMocks to unit test our BLL and DAL layer classes, but I am having trouble getting it to work. I suspect that the issue is that I am not setting up the tests properly for the code. Here is a simple example that follows the pattern of the code under test.

    First the object
    //BO
    public class Person
    {
        public int ID {get; set;}
        public string name {get; set;}
        public int age {get; set;}
        public bool isMale {get; set;}
    }

    Then the DAL
    //DAL
    public class PersonDbo
    {
        public static BO.Person GetPersonByID(int ID)
        {
            BO.Person result = new BO.Person();
             
            //Helper method our project uses
            Database db = Helper.CreateDbConnection();
             
            using (DbCommand dbCommand = db.GetStoredProcCommand("dbo.Select_Person_ByID"))
            {
                db.AddInParameter(dbCommand, "@PersonID", DbType.Int32, ID);
                 
                using (IDataReader r = db.ExecuteReader(dbCommand))
                {
                    if (r.Read())
                    {
                        result.ID = r.GetInt32(r.GetOrdinal("PersonID"));
                        result.name = r.GetString(r.GetOrdinal("Name"));
                        result.age = r.GetInt32(r.GetOrdinal("Age"));
                        result.isMale = r.GetBoolean(r.GetOrdinal("Is_Male"));
                    }
                    else
                        return null;
                    return result;
                }
            }
        }
    }
     
    Then the BLL
    //BLL
    public class PersonManager
    {
        public static BO.Person GetPerson(int ID)
        {
            BO.Person result = PersonDbo.GetPersonByID(ID);
         
            return result;
        }
    }

    And finally the test
    //Test
    [TestClass()]
    public class PersonManagerTest
    {
        [TestMethod()]
        public void GetPersonTest()
        //Arrange
        Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true};
        Mock.SetupStatic<PersonManager>(Behavior.Strict);
        Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom).MustBeCalled();
         
        //Act + Assert
        Assert.AreEqual(PersonManager.GetPerson(7), tom);
    }

    Am I doing these right?
  2. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 19 May 2011 Link to this post

    Hi Graham,

    Thanks again for bringing up the question. Your test is perfect. However, MustBeCalled is used in conjunction with Mock.Assert where you are checking if your expected call is invoked properly. But since you are doing a strict mock, it will raise mock exception anyway for calls other than the expected.

    Therefore, i modified your test in the following way:

    [TestMethod()]
    public void GetPersonTest()
    {
        //Arrange
        Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true };
        Mock.SetupStatic<PersonManager>(Behavior.Strict);
        Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom);
        //Act + Assert
        Assert.AreEqual(PersonManager.GetPerson(7), tom);
    }

    In addition i am mocking static method therefore JustMock full edition should be installed and the profiler should be configured correctly (automatically configured when you check "integrate with visual studio" option during installation).

    I am also attaching my test project to let you have a look and i am using the latest official release.

    Hope the information is useful.

    Kind regards,
    Ricky
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. DevCraft R3 2016 release webinar banner
  4. Graham
    Graham avatar
    4 posts
    Member since:
    May 2011

    Posted 19 May 2011 Link to this post

    Another long post, sorry but it is important I get these tests working properly before I make my case to purchase JustMocks to my boss.

    For some reason the tests are still hitting the database and pulling actual results rather than the ones I arrange.

    I have a custom assertion method that uses reflections to get an array of all the properties of any two objects it is given to compare then asserts they are equal on every elements (our projects have a lot of custom objects that change frequently) and I use this for my unit testing. When I execute something like this:

    [TestMethod()] 
    public void GetPersonTest() 
        //Arrange 
        Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true }; 
        Mock.SetupStatic<PersonManager>(Behavior.Strict); 
        Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom); 
        Person actual;
          
        //Act
        actual = PersonManager.GetPerson(7);
          
        //Assert
        Assert.AreEqual(actual.ID, tom.ID);
        CustomAssert.AreEqual(actual, tom);
    }

    And the actual database entry for ID = 7 is a 23 year old woman named Sarah, the first assertion will pass but the second will fail. Examining the results show that the actual object has the information for Sarah which could only have come from the database.

    I attempted to fix this by also mocking out the DAL layer component like this:
    [TestMethod()] 
    public void GetPersonTest() 
        //Arrange 
        Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true }; 
        Mock.SetupStatic<PersonManager>(Behavior.Strict);
        Mock.SetupStatic<PersonDbo>(Behavior.Strict);
        Mock.Arrange(() => PersonDbo.GerPersonByID(7).DoNothing(); //This should prevent the database from being called
        Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom); //This should set a return value for the test
        Person actual;
          
        //Act
        actual = PersonManager.GetPerson(7);
          
        //Assert
        Assert.AreEqual(actual.ID, tom.ID);
        CustomAssert.AreEqual(actual, tom);
    }

    But this also fails in the same way. I also tried replacing the DoNothing() call with an explicit Arrange statement:

    Mock.Arrange(() => PersonDbo.GerPersonByID(7).Returns(tom);

    And THIS failed too. Do you have any idea why the tests are ignoring the mocks and hitting the database anyways?

    For completeness here is a simplified version of my CustomAssert.AreEqual() method:

    public class CustomAsserts
    {
        public static void AreEqual(Object expected, Object actual, string message = "Objects do not match")
        {
            if (expected == null || actual == null)
                Assert.AreEqual(expected, actual, message);
            else
            {
                if (expected.GetType() != actual.GetType())
                    Assert.Fail(message);
      
                PropertyInfo[] prop = expected.GetType().GetProperties();
      
                foreach (PropertyInfo property in prop)
                {
                    if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.PropertyType != typeof(DateTime))
                    {
                        CustomAsserts.AreEqual(property.GetValue(expected, null), property.GetValue(actual, null));
                    }
                    else
                    {
                        Assert.AreEqual(property.GetValue(expected, null), property.GetValue(actual, null), message + ": " + property.Name + " does not match");
                    }
                }
            }
        }
    }
    note: this class requires the System.Reflection library.

    TL;DR: Mocking out the database but still getting back the actual information on the database. Tried mocking out the DAL layer as well as the BLL layer and still getting live data. Please help.
  5. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 27 May 2011 Link to this post

    Hi Graham,
    Thanks again for the reply. I am re-attaching the test project updating it using the above code and it seems to work nicely.

    Please make sure that your profiler is turned on. In case your profiler is not installed correctly or other profiling tool is overriding the target variable. In that regard you could do the following check:

    Assert.IsTrue(Mock.IsProfilerEnabled);

    Further in order to troubleshoot, you can check the current profiler version as well. For JustMock the profiler variables should look like:

    "COR_ENABLE_PROFILING", "0x1"
    "COR_PROFILER", "{D1087F67-BEE8-4f53-B27A-4E01F64F3DA8}"
    "COMPLUS_ProfAPI_ProfilerCompatibilitySetting", "EnableV2Profiler"

    You can compare this with the output from the following lines which you can run inside the vs immediate window during test debug :

    System.Environment.GetEnvironmentVariable("COR_ENABLE_PROFILING");  
    System.Environment.GetEnvironmentVariable("COR_PROFILER");

    In addition please make sure that  other mocking tool that uses profiler is not installed.

    Hope this information isuseful.

    Kind Regards,
    Ricky
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Back to Top