简体   繁体   中英

Using moq to setup a method to return a list of objects but getting null

I've been testing around in my personal projects and ran to this little problem. I have a test method that creates a list of objects, I setup a service I use in my method I test to return the mock list. How ever, for some reason the setup is not working and it is returning null.

Here is the test method:

var mockList = new List<IBillItem>
{
    new BillItem
    {
        Id = 0,
        DueDate = new DateTime(),
        Name = "",
        IndexNumber = "",
        AccountNumber = "",
        Amount = decimal.One
    },
    new BillItem
    {
        Id = 0,
        DueDate = new DateTime(),
        Name = "",
        IndexNumber = "",
        AccountNumber = "",
        Amount = decimal.One
    }
};

_billHandlingService.Setup(x => x.GetAllBillsAsync(It.IsAny<string>())).Returns(Task.FromResult(mockList));

var listBillsVm = new ListBillsViewModel(new LoggerFactory(), _billHandlingService.Object, _settingsService.Object);

await listBillsVm.GetBillsAsync();

_billHandlingService.Verify(x => x.GetAllBillsAsync(_settingsService.Name), Times.AtMostOnce);

Assert.AreEqual(1, listBillsVm.BillsList.Count);

And here is the code of the concrete class im testing:

public async Task GetBillsAsync()
{
    BillsList.Clear();

    var bills = await _billHandlingService.GetAllBillsAsync(_settingsService.LoggerUser);

    if (null != bills)
    {
        var billsByDate = bills.Where(x => x.DueDate == DateTime.Today).ToList();
        foreach (var bill in billsByDate)
        {
            BillsList.Add(bill);
            RaisePropertyChanged(nameof(BillsList));
        }
    }
}

I Have tried searching SO / google for results an yet to find any answer. Thanks in advance.

Edit: The code is not commented but I believe its clear enough, ask in comments if there's something that needs clearing

Edit 2:

Task<List<IBillItem>>GetAllBillsAsync(string username); 

Is the interface for the method being called.

You could Try changing the .Returns in the Setup to .ReturnsAsync(mockList)

//...other code removed for brevity
_billHandlingService
    .Setup(x => x.GetAllBillsAsync(It.IsAny<string>()))
    .ReturnsAsync(mockList);
//...other code removed for brevity

UPDATE

The Following minimal complete verifiable example was used based on your question to try and reproduce your issue. Note that I omitted any classes that were not necessary to create the test.

class ListBillsViewModel {
    private IBillHandlingService _billHandlingService;
    private ISettingsService _settingsService;

    public ListBillsViewModel(IBillHandlingService billHandlingService, ISettingsService settingsService) {
        this._billHandlingService = billHandlingService;
        this._settingsService = settingsService;
        BillsList = new List<IBillItem>();
    }

    public List<IBillItem> BillsList { get; set; }

    public async Task GetBillsAsync() {
        BillsList.Clear();

        var bills = await _billHandlingService.GetAllBillsAsync(_settingsService.LoggerUserName);

        if (null != bills) {
            var billsByDate = bills.Where(x => x.DueDate == DateTime.Today).ToList();
            foreach (var bill in billsByDate) {
                BillsList.Add(bill);
            }
        }
    }
}

public interface ISettingsService {
    string Name { get; }
    string LoggerUserName { get; set; }
}

public interface IBillHandlingService {
    Task<List<IBillItem>> GetAllBillsAsync(string username);
}

public class BillItem : IBillItem {
    public int Id { get; set; }
    public DateTime DueDate { get; set; }
    public string Name { get; set; }
    public string IndexNumber { get; set; }
    public string AccountNumber { get; set; }
    public decimal Amount { get; set; }
}

public interface IBillItem {
    int Id { get; set; }
    DateTime DueDate { get; set; }
    string Name { get; set; }
    string IndexNumber { get; set; }
    string AccountNumber { get; set; }
    decimal Amount { get; set; }
}

The following Unit test was then reconstructed based on the above classes

[TestMethod]
public async Task Moq_Setup_Should_Return_List_Of_Objects() {
    var mockList = new List<IBillItem>
    {
        new BillItem
        {
            Id = 0,
            DueDate = DateTime.Today,
            Name = "User",
            IndexNumber = "",
            AccountNumber = "",
            Amount = decimal.One
        },
        new BillItem
        {
            Id = 1,
            DueDate = DateTime.Today.AddDays(1),
            Name = "User",
            IndexNumber = "",
            AccountNumber = "",
            Amount = decimal.One
        }
    };

    string name = "User";

    var _settingsService = new Mock<ISettingsService>();
    _settingsService
        .Setup(m => m.Name)
        .Returns(name);
    _settingsService
        .Setup(m => m.LoggerUserName)
        .Returns(name);

    var _billHandlingService = new Mock<IBillHandlingService>();
    _billHandlingService
        .Setup(x => x.GetAllBillsAsync(It.IsAny<string>()))
        .ReturnsAsync(mockList);

    var listBillsVm = new ListBillsViewModel(_billHandlingService.Object, _settingsService.Object);

    await listBillsVm.GetBillsAsync();

    _billHandlingService.Verify(x => x.GetAllBillsAsync(_settingsService.Name), Times.AtMostOnce);

    Assert.AreEqual(1, listBillsVm.BillsList.Count);
}

I ran the above test and it passes as expected for both setups with .Returns(Task.FromResult(mockist)) and .ReturnsAsync(mockList) .

Either the example you gave does not match your actual situation or the problem is outside of what you are describing in your post.

You need to specify the List<IBillItem> on the Task.FromResult , like this:

_billHandlingService.Setup<Task<List<IBillItem>>>(
    x => x.GetAllBillsAsync(It.IsAny<string>()))
                    .Returns(Task.FromResult<List<IBillItem>>(mockList));

Similar SO Q and A here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM