Why is the response below always null in my test?
SSO.cs
public class SSO : ISSO
{
const string SSO_URL = "http://localhost";
const string SSO_PROFILE_URL = "http://localhost";
public AuthenticateResponse Authenticate(string userName, string password)
{
return GetResponse(SSO_URL);
}
public void GetProfile(string key)
{
throw new NotImplementedException();
}
public virtual AuthenticateResponse GetResponse(string url)
{
return new AuthenticateResponse();
}
}
public class AuthenticateResponse
{
public bool Expired { get; set; }
}
SSOTest.cs
[TestMethod()]
public void Authenticate_Expired_ReturnTrue()
{
var target = MockRepository.GenerateStub<SSO>();
AuthenticateResponse authResponse = new AuthenticateResponse() { Expired = true };
target.Expect(t => t.GetResponse("")).Return(authResponse);
target.Replay();
var response = target.Authenticate("mflynn", "password");
Assert.IsTrue(response.Expired);
}
Your expectation is not correct. You defined that you expect an empty string as parameter on GetResponse, but you pass in the value SSO_URL. So the expectation is not meet and null is returned instead.
You have two options to correct this
One way is to set IgnoreArguments() on the expectation
target.Expect(t => t.GetResponse("")).IgnoreArguments().Return(authResponse);
and the other way is to pass in your SSO_URL as parameter to the GetResponse method like this
target.Expect(t => t.GetResponse("http://localhost")).Return(authResponse);
Related
I'm trying to Post a request using Restsharp Client (version 108.0.3), however I'm getting an error of "Bad Request: Some of mandatory fields are missing". I know the reason the error message is showing is due to the values not being passed / sent with the request. I have tried sending in the values multiple ways, however with only one way being successful (but, this way won't work as I need to do some logic before passing the entity).
For now, I'm trying to send in only 2 values:
[DataContract]
public class UserModel : IBdeoModel
{
[Required]
//[property: JsonPropertyName("name")]
[DataMember(Name = "email")]
public string ClientEmail { get; set; }
[Required]
//[property: JsonPropertyName("password")]
[DataMember(Name = "password")]
public string ClientSecrent { get; set; }
[IgnoreDataMember]
public bool IsNameValue => true;
}
When the code is run, the folling code will be the first step to "setup" some data. A transport model is created to do some logic for data conversion depending on type (e.g. string, int, datetime) - for this step it is primarily to get the password in the required format.
public class BdeoLoginAPI : ApiRoutable, IBdeoLoginApi
{
private readonly IClient _client;
public override string MidRoute => "/prod/v2/login";
public BdeoLoginAPI(IClient client)
{
_client = client;
}
/// <summary>
/// Authenticates the request to Bdeo
/// </summary>
/// <param cref="UserModel">User Auth Model</param>
/// <returns>The result set of properties created in hubspot.</returns>
public UserTokenModel<LoginAuthDetails> AuthenticateBdeo(UserModel entity)
{
string path = GetRoute<UserModel>();
BdeoTransportObject<UserModel> transportModel = new BdeoTransportObject<UserModel>(entity);
//return _client.Execute<UserTokenModel<LoginAuthDetails>, UserModel>(path, entity, Method.Post);
return _client.Execute<UserTokenModel<LoginAuthDetails>, BdeoTransportObject<UserModel>>(path, transportModel, Method.Post);
}
}
The transport model that is being called:
[DataContract]
public class BdeoTransportObject<T> : BdeoTransportModel<T>
{
public BdeoTransportObject() { }
public BdeoTransportObject(T model)
{
ToPropertyTransportModel(model);
}
}
[DataContract]
public abstract class BdeoTransportModel<T>
{
private Dictionary<string, object> Properties { get; set; }
internal void ToPropertyTransportModel(T model)
{
var propertiesToAdd = new Dictionary<string, object>();
PropertyInfo[] modelProperties = model.GetType().GetProperties();
foreach (PropertyInfo modelProp in modelProperties)
{
var memberAttrib = modelProp.GetCustomAttribute(typeof(DataMemberAttribute)) as DataMemberAttribute;
object modelValue = modelProp.GetValue(model);
if (modelValue == null || memberAttrib == null || modelValue.ToString() == string.Empty)
{
continue;
}
//some other logic
propertiesToAdd.Add(memberAttrib.Name, modelValue);
}
Properties = propertiesToAdd;
}
}
Then finally doing the actual RestRequest call.
public T Execute<T, K>(string absoluteUriPath, K entity, Method method = Method.Get) where T : new()
=> SendReceiveRequest<T, K>(absoluteUriPath, method, entity);
private RestRequest ConfigureRequestAuthentication(string path, Method method)
{
string fullPath = $"{BasePath.TrimEnd('/')}/{path.Trim('/')}";
RestRequest request = new RestRequest(fullPath, method);
request.RequestFormat = DataFormat.Json;
return request;
}
private T SendReceiveRequest<T, K>(string path, Method method, K entity) where T : new()
{
RestRequest request = ConfigureRequestAuthentication(path, method);
if (!entity.Equals(default(K)))
{
//string json = System.Text.Json.JsonSerializer.Serialize(entity);
//string json = JsonConvert.SerializeObject(entity);
//request.AddJsonBody(entity);
//string content = JsonConvert.SerializeObject(entity, Formatting.Indented);
request.AddBody(entity);
//request.AddParameter("text/json", entity, ParameterType.RequestBody);
}
var response = _client.Execute<T>(request);
if (!response.IsSuccessful)
{
throw new InvalidOperationException("Failed with " + response.StatusCode.ToString() + ". Error Message: " + response.ErrorMessage);
}
return response.Data;
}
When sending the entity through, the data is definately present, however it seems it is not serializing as it should and throwing the error of BadRequest - mandatory fields are missing.
However, when I take out the middle step for the transport model, it works fine. Making the necessarily alterations to get it to work looks like this:
[DataContract]
public class UserModel : IBdeoModel
{
[Required]
public string email { get; set; }
[Required]
public string password { get; set; }
[IgnoreDataMember]
public bool IsNameValue => true;
}
public UserTokenModel<LoginAuthDetails> AuthenticateBdeo(UserModel entity)
{
string path = GetRoute<UserModel>();
BdeoTransportObject<UserModel> transportModel = new BdeoTransportObject<UserModel>(entity);
return _client.Execute<UserTokenModel<LoginAuthDetails>, UserModel>(path, entity, Method.Post);
// return _client.Execute<UserTokenModel<LoginAuthDetails>, BdeoTransportObject<UserModel>>(path, transportModel, Method.Post);
}
It seems that adding these properties to a dictionary type in the transportmodel is causing the issue when Restharp attempts to serialize it, however I can't seem to see what is wrong to get it to work.
Here is the method that I am going to test and I want IsPhoneNomValid() would return false so then I would be able to assert my expectations:
public async Task<UserResponseDto> RegisterUser(RegistrationRequestDto register, CancellationToken cancelationToken)
{
// I want the IsPhoneNomValid() method, Would return "FALSE"
var isPhoneNumberValid = register.PhoneNumber.IsPhoneNomValid();
if (!isPhoneNumberValid)
return new UserResponseDto
{
Status = new StatusMaker().ErrorStatus("Some Error Message")
};
var isActiveAccountPhoneNumberExists = await IsActiveAccountPhoneNumberExist(register.PhoneNumber, cancelationToken);
if (isActiveAccountPhoneNumberExists.Status == "error")
return new UserResponseDto
{
Status = isActiveAccountPhoneNumberExists
};
}
RegisterUser_MustReturnPhoneNumberError is my Test method:
public class AccountUserTests
{
private Mock<IUserService> _userService { get; set; }
public AccountUserTests()
{
_userService = new Mock<IUserService>();
}
public async Task RegisterUser_MustReturnPhoneNumberError()
{
//Arrang
// in here I want to setup IsPhoneNomValid() would return false.
//Act
//Assert
}
}
Is there any way that I can test the static methods which are used in my main function which I am testing ?
Here is the IsPhoneNomValid() codes:
public static class Validation
{
public static bool IsPhoneNomValid(this string phoneNumber)
{
//TODO Does it need to be foreign phone numbers ?
var isMatch = Regex.Match(phoneNumber, #"^09[0-9]{9}$");
if (isMatch.Success)
return true;
return false;
}
}
You want to test your static method IsPhoneNomValid.
[Theory]
[InlineData("123456789")]
public void TestMethod(string phoneNumber)
{
bool isPhoneNumber =Validation.IsPhoneNomValid(phoneNumber);
Assert.True(isPhoneNumber);
}
With InlineData, you can test with multiple phone numbers.
The best option is to use a really invalid phone number in your case. But I have a lib SMock that can do what you want. Here is an example of usage:
public async Task RegisterUser_MustReturnPhoneNumberError()
{
Mock.Setup(context => Validation.IsPhoneNomValid(context.It.IsAny<string>()), async () =>
{
// You must test RegisterUser method in this scope
// Here Validation.IsPhoneNomValid will always return false
var result = await RegisterUser(register, ct);
Assert.AreEqual(expectedStatus, result.Status);
}).Returns(false);
}
I'm new at working on the abp.io framework, precisely Angular + Entity Framework Core.
I want to be able to create or display an objects list of a class that I've created.
For example, I've made a class called Address on the Domain layer.
Here is its AppService on the Application layer:
namespace ASKOM.RefPlusStudio.core.Services
{
[Authorize(corePermissions.Addresses.Default)]
public class AddressAppService : coreAppService, IAddressAppService
{
private readonly IAddressRepository _addressRepository;
private readonly AddressManager _addressManager;
public AddressAppService(IAddressRepository addressRepository, AddressManager addressManager)
{
_addressRepository = addressRepository;
_addressManager = addressManager;
}
[Authorize(corePermissions.Addresses.Create)]
public async Task<AddressDto> CreateAsync(CreateUpdateAddressDto input)
{
var address = await _addressManager.CreateAsync(
input.StreetNumber,
input.StreetName,
input.PostalCode,
input.City,
input.Country
);
await _addressRepository.InsertAsync(address);
return ObjectMapper.Map<Address, AddressDto>(address);
}
[Authorize(corePermissions.Addresses.Delete)]
public async Task DeleteAsync(Guid id)
{
await _addressRepository.DeleteAsync(id);
}
public async Task<AddressDto> GetAsync(Guid id)
{
var address = await _addressRepository.GetAsync(id);
return ObjectMapper.Map<Address, AddressDto>(address);
}
public async Task<PagedResultDto<AddressDto>> GetListAsync(GetAddressListDto input)
{
if (input.Sorting.IsNullOrWhiteSpace())
{
input.Sorting = nameof(Address.Country);
}
var addresses = await _addressRepository.GetListAsync(
input.SkipCount,
input.MaxResultCount,
input.Sorting,
input.Filter
);
var totalCount = await AsyncExecuter.CountAsync(
_addressRepository.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
address => address.Country.Contains(input.Filter)
)
);
return new PagedResultDto<AddressDto>(
totalCount,
ObjectMapper.Map<List<Address>, List<AddressDto>>(addresses)
);
}
[Authorize(corePermissions.Addresses.Edit)]
public async Task UpdateAsync(Guid id, CreateUpdateAddressDto input)
{
var address = await _addressRepository.GetAsync(id);
address.StreetNumber = input.StreetNumber;
address.StreetName = input.StreetName;
address.PostalCode = input.PostalCode;
address.City = input.City;
address.Country = input.Country;
await _addressRepository.UpdateAsync(address);
}
}
}
I gave them all the permissions needed.
Here is corePermissions.cs :
namespace ASKOM.RefPlusStudio.core.Permissions
{
public static class corePermissions
{
public const string GroupName = "core";
//Add your own permission names. Example:
//public const string MyPermission1 = GroupName + ".MyPermission1";
public static class Addresses
{
public const string Default = GroupName + ".Addresses";
public const string Create = Default + ".Create";
public const string Edit = Default + ".Edit";
public const string Delete = Default + ".Delete";
}
}
}
I wanted to see if it can display an Addresses list so I've made a static one on DataSeeder:
namespace ASKOM.RefPlusStudio.core
{
public class coreDataSeederContributor : IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Address, Guid> _addressRepository;
private readonly IGuidGenerator _guidGenerator;
public coreDataSeederContributor(IRepository<Address, Guid> addressRepository, IGuidGenerator guidGenerator)
{
_addressRepository = addressRepository;
_guidGenerator = guidGenerator;
}
public async Task SeedAsync(DataSeedContext context)
{
if (await _addressRepository.GetCountAsync() > 0)
{
return;
}
var address = new Address(
id: _guidGenerator.Create(),
streetNumber: 07,
streetName: "Med Salah Belhaj",
postalCode: 2080,
city: "Ariana",
country: "Tunisie"
);
//autoSave: true
await _addressRepository.InsertAsync(address);
}
}
}
Here is now the result on Swagger UI:
When I try to open the request URL, here is what it shows:
I'm sure that I may have forgotten something and that's why I get Access Denied on the Request URL, but I don't really know what it is because I'm new at this.
Could you please help me?
Thank you
There was a problem with the database. That's why it hasn't read the data I've provided in the DataSeedProvider.
I am using Rhino Mocks to stub out the functionality of a SOAP endpoint and for the most part it works. But, the interface is quite quirky and I am struggling to get the following to work (i have renamed the classes for simplicity)
public interface IWebService
{
void CopyFile(Request request);
}
public interface IService
{
void CopyFile(string filename, byte[] data);
}
public class Request
{
public string Filename { get; set; }
public byte[] Data { get; set; }
}
public class Service : IService
{
IWebService _service;
public Service(IWebService service)
{
_service = service;
}
public void CopyFile(string filename, byte[] data)
{
_service.CopyFile(new Request() {Filename = filename,Data = data });
}
}
Now, in my test I have something like this
[TestCase]
public void TestFileCopyFailsIfFilenameIsMissing()
{
IWebService serviceMock = MockRepository.GenerateMock<IWebService>();
serviceMock.Expect(x => x.CopyFile(Arg<Request>.Is.Equal(new Request() { Filename = Arg<string>.Is.Null, Data = Arg<byte[]>.Is.Anything }))).Throw(new Exception());
Service service = new Service(serviceMock);
service.CopyFile(null, new byte[] { });
}
Which throws the exception:
An exception of type 'System.InvalidOperationException' occurred in Rhino.Mocks.dll but was not handled in user code
Additional information: Use Arg ONLY within a mock method call while recording. 1 arguments expected, 3 have been defined.
I have tried the all possibilities in the world on this one, but cant get it right. If i dont use Arg and use
Expect(null, new byte[]{});
it will always pass no matter what
I suggest to use WhenCalled and in this method check Request object.
bool isCorrectParam = false;
IWebService serviceMock = MockRepository.GenerateMock<IWebService>();
serviceMock.Expect(x => x.CopyFile(null))
.IgnoreArguments()
.WhenCalled(x =>
{
Request req = x.Arguments[0] as Request;
if (req.Data.Count() == 0 && req.Filename == null)
{
isCorrectParam = true;
}
});
Service service = new Service(serviceMock);
service.CopyFile(null, new byte[] { });
Assert.IsTrue(isCorrectParam);
you can also use Matches...
serviceMock.Expect(x => x.CopyFile(Arg<Request>.Matches(r => r.FileName==null))).Throw(new Exception());
We are using the OAuthAuthorizationServerProvider class to do authorization in our ASP.NET Web Api app.
If the provided username and password is invalid in GrantResourceOwnerCredentials, the call
context.SetError( "invalid_grant", "The user name or password is incorrect." );
Produces the following Json result:
{
"error": "invalid_grant",
"error_description": "The user name or password is incorrect."
}
Is there any way to customize this error result?
I would like to make it consistent with default error message format used in other parts of the API:
{
"message": "Some error occurred."
}
Is this possible to achieve with the OAuthAuthorizationServerProvider?
This is how I did it.
string jsonString = "{\"message\": \"Some error occurred.\"}";
// This is just a work around to overcome an unknown internal bug.
// In future releases of Owin, you may remove this.
context.SetError(new string(' ',jsonString.Length-12));
context.Response.StatusCode = 400;
context.Response.Write(jsonString);
+1 for Dasun's answer. Here is how I extended it a bit further.
public class ErrorMessage
{
public ErrorMessage(string message)
{
Message = message;
}
public string Message { get; private set; }
}
public static class ContextHelper
{
public static void SetCustomError(this OAuthGrantResourceOwnerCredentialsContext context, string errorMessage)
{
var json = new ErrorMessage(errorMessage).ToJsonString();
context.SetError(json);
context.Response.Write(json);
}
}
The .ToJsonString() is another extension method that uses the Newtonsoft.Json library.
public static string ToJsonString(this object obj)
{
return JsonConvert.SerializeObject(obj);
}
Usage:
context.SetCustomError("something went wrong");
1+ again for "user2325333" and "Dasun's" answer his solution, your answers are good but still there is an issue .
The Josn Tag still return {error:""}, thus I replace the context.Response.Body with empty MemoryStream
and here the work example
public static class ContextHelper
{
public static void SetCustomError(this OAuthGrantResourceOwnerCredentialsContext context,string error, string errorMessage)
{
var json = new ResponseMessage
{ Data = errorMessage, Message = error, IsError = true }.ToJsonString();
context.SetError(json);
context.Response.Write(json);
Invoke(context);
}
public static string ToJsonString(this object obj)
{
return JsonConvert.SerializeObject(obj);
}
static async Task Invoke(OAuthGrantResourceOwnerCredentialsContext context)
{
var owinResponseStream = new MemoryStream();
var customResponseBody = new System.Net.Http.StringContent(JsonConvert.SerializeObject(new ResponseMessage()));
var customResponseStream = await customResponseBody.ReadAsStreamAsync();
await customResponseStream.CopyToAsync(owinResponseStream);
context.Response.ContentType = "application/json";
context.Response.ContentLength = customResponseStream.Length;
context.Response.Body = owinResponseStream;
}
}
public class ResponseMessage
{
public bool IsError { get; set; }
public string Data { get; set; }
public string Message { get; set; }
}
for usage of this context
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (!context.Match.Passcode)
{
context.SetCustomError("invalid_grant", "Passcode is invalid.");
return;
}
}
The Result will be as