0

I need to write some unit test cases to test my code in C# Visual Studio Team Test framework. Below is the method I want to test:

public static ObjectID CreateObjectID(ObjectID xrmObjectID)

{

        return new ObjectID
        {
            Id = xrmAssociation.ID != null ? xrmAssociation.ID.Id : Guid.Empty;
        };
}

In the above method, I need to write unit test cases to cover the conditional statements, for example:

Id = xrmAssociation.ID != null ? xrmAssociation.ID.Id : Guid.Empty;

So I wrote the following unit test method:

namespace WebApi.Test
{
    [TestClass]
    public class ApiTest
    {
        [TestMethod]
        [ExpectedException(typeof(NullReferenceException), "A userId of null was inappropriately allowed.")]
        public void CreateObjectIDShouldCheckConditionalBranch()
        {
            Xrm.objectID Input = new Xrm.objectID();
            Input = null;
            WebApiRole.Api.CreateObjectID(Input);
            var expected = default(WebApi.ObjectID);
            Assert.IsTrue(expected == WebApi.CreateObjectID(Input), "Failed");
        }
    }
}

This test passed, but it is actually not testing what I intend to test i.e. It should assign "Guid.Empty" when "null" is being passed. It just throws the exceptions of NullReference and thus the test passes.

  • 1
    Your question is not particularly clear since you haven't told us why the test case is not correct - do you get an error, unexpected results, something else entirely? Also writing in bold is particularly jarring and should only be used where emphasis is necessary – RobV Nov 11 '14 at 11:40
  • I can see several problems at a glance - one your `expected` value is an integer but your actual value is an instance of your class so they are unlikely to meet an `AreEqual()` assertion. Secondly your actual logic assumes a non-null input but you pass in a `null` so you may well be getting a `NullPointerException`. However without further details your question will be hard to answer and may likely be closed – RobV Nov 11 '14 at 11:44
  • The test is not correct since I want to test for only specific statements in that method and I don't have much knowledge on Unit Testing, this is my first time on Stack Overflow, I am stuck with this unit test and unable to move on. The test is failing. Can you point me in the correct direction by example of some code-snippets? – Abhishek Agrawal Nov 11 '14 at 11:46
  • Sir, In the above method, I need to write unit test cases for specific statements having if-else logic to cover the conditional statements, for example: CreatedByUserProfileId = xrmAssociation.pv_CreatedByUserProfileID != null ? xrmAssociation.pv_CreatedByUserProfileID.Id : Guid.Empty; – Abhishek Agrawal Nov 11 '14 at 11:48
  • StackOverflow is not a code writing service it is for solving *specific programming problems*. As it stands you haven't stated a specific problem - you say the test fails in which case you should have an error or a failure message which you should edit your answer to include (see the `edit` button under your answer). If you add that then you will most likely have a specific question that people can actually answer – RobV Nov 11 '14 at 11:48
  • @RobV I have edited the post and included result I get when I ran the test, does it pass the community requirements now? – Abhishek Agrawal Nov 11 '14 at 11:53
  • @Abishek: without the use of reflection, I can't see you accomplishing your goals. I think what you're looking to test are fields which are `non-string reference types` and any `Nullable` types. Is this a fairly correct summation of your testing needs? – code4life Nov 11 '14 at 13:24
  • By the way, the `ExpectedException` is hardcoded to report that `userId` failed the test -- when in reality you're testing for other fields, too... right? – code4life Nov 11 '14 at 13:27
  • Right! And about the hardcoded line, I know I am just too worried about getting it to work first. – Abhishek Agrawal Nov 11 '14 at 13:30

2 Answers2

1

I'd suggest writing one test for each separate case. That way, you can more easily tweak the testing code should requirements change.

I'd proceed like this (and I'll also take a guess and assume you're modelling Dynamics CRM, judging by the data)

[TestMethod]
public void AssociationCreationFromXrmShouldDefaultWhenAssociationHoldingIsNull()
{
    Xrm.pv_association input = new Xrmpv_association();
    input.pv_AssociationHolding = null;

    var output = PVWebApiRole.ApiModelFactory.CreateAssociationFromXrm(Input);

    // The fact that 'output' is valid should be tested separately
    Assert.AreEqual(output.AssociationHoldingId, Guid.Empty);
}
[TestMethod]
public void AssociationCreationFromXrmShouldKeepNotNullAssociationHolding()
{
    var sampleReference = new EntityReference("yourlogicalName", Guid.Parse("00000000-0000-0000-0000-000000000000"));
    Xrm.pv_association input = new Xrmpv_association();
    input.pv_AssociationHolding = sampleReference;

    var output = PVWebApiRole.ApiModelFactory.CreateAssociationFromXrm(Input);

    // The fact that 'output' is valid should be tested separately
    Assert.AreEqual(output.AssociationHoldingId, sampleReference.Id);
}            

and so on and so forth, two tests for each field, one to test the true side of the conditional and one for the false side (a couple of generic methods, one for OptionSet fields and one for EntityReference fields could be built and called several times, making the code short and fast to write).

Also, I think you should tweak CreateAssociationFromXrm to make it throw an ArgumentException if input is null (a couple tests of specifically that are of course to be written beforehand).

Alex
  • 23,004
  • 4
  • 39
  • 73
0

Using the ExpectedException annotation can be risky particularly when checking for a generic exception like NullReferenceException that could be thrown in other circumstances.

It seems like what you want to do is check that a specific property is not null in which case you would be much better off using the IsNotNull() assertion e.g.

var actual = PVWebApiRole.ApiModelFactory.CreateAssociationFromXrm(Input);
Assert.IsNotNull(actual.CreatedByUserProfileId);

For general help on debugging your NullReferenceException see What is a NullReferenceException and how do I fix it?

As I already pointed out in my comments your problem is that your CreateAssociationFromXrm() method assumes the xrmAssociation parameter is non-null when it does checks like the following:

xrmAssociation.pv_CreatedByUserProfileID != null ? xrmAssociation.pv_CreatedByUserProfileID.Id : Guid.Empty

You can avoid this by adding null checks to specific conditional statements e.g.

xrmAssociation != null && xrmAssociation.pv_CreatedByUserProfileID != null ? xrmAssociation.pv_CreatedByUserProfileID.Id : Guid.Empty

Stylistic suggestion

Often it is better to disallow null inputs completely so you may actually want to check for null at the start of your method and throw an ArgumentNullException e.g.

public static Association CreateAssociationFromXrm(Xrm.pv_association xrmAssociation)
{
  if (xrmAssociation == null) throw new ArgumentNullException("xrmAssociation", "xrmAssociation cannot be null");

  // Rest of your existing logic goes here
}
Community
  • 1
  • 1
RobV
  • 28,022
  • 11
  • 77
  • 119
  • "It seems like what you want to do is check that a specific property is not null in which case you would be much better off using the IsNotNull() assertion" I am already checking this thing through the below unit test case: [TestMethod] public void CreateAssociationFromXrmShouldCreateInstanceWithDefaultValues() { Xrm.pv_association xrmAssociation = new Xrm.pv_association(); var association = PVWebApiRole.ApiModelFactory.CreateAssociationFromXrm(xrmAssociation); Assert.IsNotNull(association); } – Abhishek Agrawal Nov 11 '14 at 12:17
  • I **want to** pass null values and it should assign "Guid.Empty" when "null" is being passed through the conditional branch execution. I need the TestMethod to check that. – Abhishek Agrawal Nov 11 '14 at 12:22
  • As I pointed out in my answer you can do that by correcting the conditional checks in your code. The change to disallow `null` parameters was a stylistic suggestion (and I have clarified this in my answer) which you are free to ignore. – RobV Nov 11 '14 at 12:27
  • Thank you, I have made the changes suggested by you. Though it provides better programming practice, your changes obliterate the use for a Unit Test case for the scenario I am intending to check whether "Guid.Empty" is passed in case of null input by user. But in my project, in the web form those fields like "CreatedByUserProfileID" are optional so if user leaves it blank, I want it to populate its "default(type)" or "" value instead of storing null values. – Abhishek Agrawal Nov 11 '14 at 12:47