asp.net core testing controller with IStringLocalizer
Asked Answered
A

2

23

I have controller with localization

public class HomeController : Controller
{
    private readonly IStringLocalizer<HomeController> _localizer;

    public HomeController(IStringLocalizer<HomeController> localizer)
    {
        _localizer = localizer;
    }

    [HttpPost]
    public IActionResult SetLanguage(string culture, string returnUrl)
    {
        Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
            new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
        );

        return LocalRedirect(returnUrl);
    }

    public IActionResult Index()
    {
        ViewData["MyTitle"] = _localizer["Hello my dear friend!"];

        return View("Index");
    }
}

and I added xUnit project for testing and wrote next code

public class HomeControllerTest
{
    private readonly IStringLocalizer<HomeController> _localizer;
    private HomeController _controller;
    private ViewResult _result;

    public HomeControllerTest()
    {
        _controller = new HomeController(_localizer);
        _result = _controller.Index() as ViewResult;
    }

    [Fact]
    public void IndexViewDataMessage()
    {
        // Assert
        Assert.Equal("Hello my dear friend!", _result?.ViewData["MyTitle"]);
    }

    [Fact]
    public void IndexViewResultNotNull()
    {
        // Assert
        Assert.NotNull(_result);
    }

    [Fact]
    public void IndexViewNameEqualIndex()
    {
        // Assert
        Assert.Equal("Index", _result?.ViewName);
    }
}

When I running all tests, they returns false with exception:

Message: System.NullReferenceException : Object reference not set to an instance of an object.

When you double-click on a method in the StackTrace cursor appears on the line

ViewData["MyTitle"] = _localizer["Hello my dear friend!"];

I think this is due to IStringLocalizer. How to fix it? May be somebody knows what is the reason?

Alastair answered 17/4, 2017 at 22:51 Comment(1)
Well at no point do you assign a value to localizer so it is going to be null. You need to create mock of the dependency and set it up to return an expected value for the testAmmamaria
A
33

Setup the mock to return your expected result.

var mock = new Mock<IStringLocalizer<HomeController>>();
string key = "Hello my dear friend!";
var localizedString = new LocalizedString(key, key);
mock.Setup(_ => _[key]).Returns(localizedString);

_localizer = mock.Object;
_controller = new HomeController(_localizer);
Ammamaria answered 18/4, 2017 at 0:5 Comment(1)
Is there any chance to set manual locale for IStringLocalizer? I am trying to test a method which calls IStringLocalizer<MyClass>, I am passing an instance of it, but can't figure out how to set locale. I tried _myLocalizerVar.WithCulture(new CultureInfo("fr-FR")), but it creates a new instance of StringLocalizer, which is not what I want.Claribel
E
25

If you need strings from the actual localized resources in your tests you can add the Microsoft.AspNetCore.All Nuget package to your test project and then use the following code:

var options = Options.Create(new LocalizationOptions {ResourcesPath = "Resources"});
var factory = new ResourceManagerStringLocalizerFactory(options, NullLoggerFactory.Instance);
var localizer = new StringLocalizer<HomeController>(factory);

The ResourcesPath should be the relative path of where HomeController.en.resx is found from the project root.

Ettie answered 6/11, 2019 at 21:0 Comment(2)
Thank you for the answer, worked out perfectly, but I didn't need to install the package Microsoft.AspNetCore.All. My project is a dotnet core 3.1.Groyne
Thanks for this answer, works perfectly for me since i have a custom factory as wellCavalryman

© 2022 - 2024 — McMap. All rights reserved.