Reputation: 3775
I have set up a TestProject in Visual Studio for Mac that references my Xamarin Forms project for testing the non-visual portions of my code.
However I am getting the following error when I try to test a piece of my code that leverages Xamarin.Auth to access the keychain.
System.NotImplementedException :
Portable Bait And Switch is nuget feature, so the package must be installed in all project.
NotImplementedException will indicate that Portable Code from PCL is used and not Platform Specific
implementation. Please check whether platform specific Assembly is properly installed.
Cannot save account in Portable profile - bait-and-switch error.
Please file a bug in https://bugzilla.xamarin.com
This code works fine running on the iOS simulator, and I assume it has something to do with the way xamarin auth leverages the ios Keychain which is not present in this test project. I tried to add my ios solution in references, but I am unable to do so in "edit references" of my test project. The project references dialog wont permit it:
Here is the code that is failing in my PCL.
AccountStore store;
store = AccountStore.Create();
Apparently it has trouble with AccountStore.Create()
Here is the testcode class that calls the PCL:
using System;
using NUnit.Framework;
using CrowdWisdom;
using CrowdWisdom.Authentication;
namespace CrowdWisdomTest
{
[TestFixture()]
public class AuthServiceTest
{
[Test()]
public void SaveRestoreSecret()
{
String secret = "ABCD";
AuthService auth = AuthService.GetInstance();
auth.putSecret("MySecret", secret);
Assert.AreEqual(secret, auth.GetSecret("MySecret"));
}
}
}
Upvotes: 1
Views: 522
Reputation: 1009
I had the same issue, in my case the Xamarin.Auth version was the same (1.7.0) in all projects. I solved the issue by editing the .csproj in this way:
<Reference Include="Xamarin.Auth, Version=1.6.0.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xamarin.Auth.1.7.0\lib\MonoAndroid10\Xamarin.Auth.dll</HintPath>
<Private>True</Private>
</Reference>
Adding the tag <Private>True</Private>
solved the issue for me.
The reference must be present and with this tag in .csproj files.
Upvotes: 0
Reputation: 13601
Bait And Switch pattern that most cross-platform plugins use - is not a very unit-test friendly pattern. As you can see in your example.
My very first recommendation would be to use a contract based approach, alongwith with a dependency-injection container for your authorization process; so that you can provide a mock implementation as unit-test context. But if that is not possible, then you can use following hack to provide your own mock-switch for these static classes.
Basically, the error you see is because your portable code is accessing the portable version of Xamarin.Auth which is just intended to be the bait. So you will have to create your own implementation to act as switch in unit-test context (as they have done in platform specific libraries in Xamarin.Auth).
In order to do that, you will need to:
Create another portable library (which will only be used by your unit-test project). Let's say we name it Xamarin.Auth.Mocks
. Make sure to update the root namespace, and assembly name as 'Xamarin.Auth' in its properties page.
Add a mock account store class and implement AccountStore
using switch pattern.
namespace Xamarin.Auth
{
/// <summary>
/// A persistent storage for <see cref="Account"/>s. This storage is encrypted.
/// Accounts are stored using a service ID and the username of the account
/// as a primary key.
/// </summary>
#if XAMARIN_AUTH_INTERNAL
internal abstract partial class AccountStore
#else
public abstract partial class AccountStore
#endif
{
public static AccountStore Create()
{
return new MockAccountStore();
}
}
public class MockAccountStore : AccountStore
{
}
}
Add reference to Xamarin.Auth.Mocks
in your unit-test library
Now every time you run your unit-tests, your portable code, will find your mock switch implementation for all their Xamarin.Auth
needs, and you achieve true isolation from Xamarin.Auth
; which technically is something we aspire to anyways when we write unit-test(s).
Note: If your portable code uses other bait-switch classes, add mock implementation for them too in your Xamarin.Auth.Mocks
library. You only need to add mock classes for the ones that you use in your code; not all of the classes in Xamarin.Auth
Upvotes: 3