chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
+1 vote

Hi,

I am trying to test if property (List of Field(s)) was initialized correctly in constructor. However I cannot access this property directly, only via method, which cast Field to object

I think, because of the cast, I got back "TypeMock.TypeMockException: ***Cannot verify on real object -use a fake object instead" when trying to verify property was set / not set.

Please see the code example below:

(example should be executable)


class Field
{
    public string Name { get; set; }

    public string Description { get; set; }

    private int? _value;

    public int? Value
    {
        set => _value = value;
    }
}

class FieldSection
{
    private List<Field> Fields { get; }

    public FieldSection(IDictionary<string, int> fieldValues)
    {
        Fields = new List<Field>();

        foreach (var value in fieldValues)
        {
            if ((value.Value % 2) == 0)
            {
                Fields.Add(new Field { Name = value.Key });
            }
            else
            {
                Fields.Add(new Field { Name = value.Key, Value = value.Value }); 
            }
        }
    }

    public List<object> GetAvailableFields()
    {
        return Fields.Select(field => (object) field).ToList();
    }
}

[Test]
public void Test2()
{

    var fieldValues = new Dictionary<string, int> { {\"field1\", 1}, {\"field2\", 2} };

    // fake future objects, which gets created in FieldSection constructor
    var fakeField1 = Isolate.Fake.NextInstance<Field>();
    fakeField1.Description = \"FakeField1\";

    var fakeField2 = Isolate.Fake.NextInstance<Field>();
    fakeField2.Description = \"FakeField2\";

    var fieldSection = new FieldSection(fieldValues);

    // get back fakes via GetAvailableFields(), which cast fakes to objects
    var availableFields = fieldSection.GetAvailableFields();
    
    // verify Field objects were created correctly
    foreach (Field field in availableFields)
    {
        var fieldValue = fieldValues[field.Name];

        if ((fieldValue % 2) == 0)
        {
            Isolate.Verify.WasNotCalled(() => field.Value = fieldValue);
        }
        else
        {
            // here comes the error: TypeMock.TypeMockException : ***Cannot verify on real object -use a fake object instead
            Isolate.Verify.WasCalledWithExactArguments(() => field.Value = fieldValue);
        }
    }
}


How can I cast field from availableFields back to Typemock fake object, so I will not get an error?

asked by Ctvt (2.7k points)

2 Answers

0 votes

One option to fix this error would be to change the return type of the GetAvailableFields method to a list of Field objects instead of a list of object objects, so you can directly access the Field objects in your test without having to cast them.

Alternatively, if you want to keep the return type of GetAvailableFields as a list of object objects, you can use the As method of the Isolate class to cast the objects in the list back to their original fake Field objects before verifying the calls on them.

Here's how you can modify your test to use the As method:

[Test]

public void Test2()

{

    var fieldValues = new Dictionary<string, int> { {"field1", 1}, {"field2", 2} };

    // fake future objects, which gets created in FieldSection constructor

    var fakeField1 = Isolate.Fake.NextInstance<Field>();

    fakeField1.Description = "FakeField1";

    var fakeField2 = Isolate.Fake.NextInstance<Field>();

    fakeField2.Description = "FakeField2";

    var fieldSection = new FieldSection(fieldValues);

    // get back fakes via GetAvailableFields(), which cast fakes to objects

    var availableFields = fieldSection.GetAvailableFields();

    

    // verify Field objects were created correctly

    foreach (object obj in availableFields)

    {

        var field = Isolate.As<Field>(obj);

        var fieldValue = fieldValues[field.Name];

        if ((fieldValue % 2) == 0)

        {

            Isolate.Verify.WasNotCalled(() => field.Value = fieldValue);

        }

        else

        {

            Isolate.Verify.WasCalledWithExactArguments(() => field.Value = fieldValue);

        }

    }

}

This should fix the error you are seeing. I hope.

answered by Johnathon00 (190 points)
0 votes

Hi, smiley

You cannot use Verify on objects of the future fakes. In your case, you used " Isolate.Verify.WasNotCalled(() => field.Value = fieldValue); ",  but since filed is a future fake, this cannot be done. if you change it to something like " Isolate.Verify.WasNotCalled(() => fakeField1.Value = fieldValue);", it will pass accordingly.

In addition, check out this version of the code:

using NUnit.Framework;
using Typemock.Isolator;

[TestFixture, Isolated]
public class FieldSectionTests
{
    private FieldSection fieldSection;
    private Field fakeField1;
    private Field fakeField2;

    [SetUp]
    public void SetUp()
    {
        var fieldValues = new Dictionary<string, int> { { "field1", 2 }, { "field2", 4 } };

        fakeField1 = Isolate.Fake.Instance<Field>();
        fakeField1.Description = "FakeField1";

        fakeField2 = Isolate.Fake.Instance<Field>();
        fakeField2.Description = "FakeField2";

        // Act
        fieldSection = new FieldSection(fieldValues);
    }

    [Test]
    public void FieldSection_ConstructedWithEvenValues_FieldsNotAssignedValue()
    {
        // Assert
        Isolate.Verify.WasNotCalled(() => fakeField1.Value = 0);
        Isolate.Verify.WasNotCalled(() => fakeField2.Value = 0);
    }

    [Test]
    public void FieldSection_ConstructedWithOddValues_FieldsAssignedValue()
    {
        // Assert
        Isolate.Verify.WasNotCalled(() => fakeField1.Value = 0);
        Isolate.Verify.WasCalledWithExactArgument(() => fakeField2.Value = 4);
    }
}


  1. In this updated code, the Isolated attribute was added to the test class to indicate that it should be handled by Typemock Isolator. This ensures that the necessary Typemock framework integration is applied during the test execution.
  2. Split test in 2 so they test a specific thing.
  3. Setup Method (SetUp): a setup method was added annotated with the [SetUp] attribute. The setup method is executed before each test method in the test fixture. In this setup, we create the fake instances of the Field class and initialize the FieldSection with the provided values. By doing this, we avoid repeating the same setup code in each test method.
  4. Improved Assertion: the assertion statements were updated using Isolate.Verify.WasNotCalled and Isolate.Verify.WasCalledWithExactArgument.
Hope this helps, and happy testing cool
answered by Erel_TypeMock (2.6k points)
...