简体   繁体   中英

How to test a method when I don't know random id which is primaryKey of database item

Can You tell me how to test edit method, i have to match two products but i can't do that becouse I don't know primaryKey which is randomly generated.

This is method code:

public Product editProduct(PrimaryKey primaryKey, Product content) {

    Map<String, Object> map = new HashMap<>();
    map.put("name", content.getName());
    map.put("calories", content.getCalories());
    map.put("fat", content.getFat());
    map.put("carbo", content.getCarbo());
    map.put("protein", content.getProtein());
    map.put("productKinds", content.getProductKinds());
    map.put("author", content.getAuthor());
    map.put("media", content.getMedia());
    map.put("approved", content.getApproved());

    UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(primaryKey).withValueMap(map);

    UpdateItemOutcome itemOutcome = databaseController.getTable(PRODUCT_TABLE).updateItem(updateItemSpec);


    Product product = new Product();
    product.setName(itemOutcome.getItem().get("name").toString());
    product.setCalories(itemOutcome.getItem().getInt("calories"));
    product.setFat(itemOutcome.getItem().getDouble("fat"));
    product.setCarbo(itemOutcome.getItem().getDouble("carbo"));
    product.setProtein(itemOutcome.getItem().getDouble("protein"));
    product.setProductKinds(itemOutcome.getItem().getList("productKinds"));

    ObjectMapper objectMapper = new ObjectMapper();
    try {
        Author productAuthor = objectMapper.readValue(itemOutcome.getItem().getString("author"), Author.class);
        product.setAuthor(productAuthor);
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        Media productMedia = objectMapper.readValue(itemOutcome.getItem().getString("media"), Media.class);
        product.setMedia(productMedia);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return product;
}

I think I did this fine but if You see something wrong please tell me that. I'm begginer and I've never used AWS before.

And this is Test code:

@Test
public void editProduct() throws Exception {

    KitchenService instance = new KitchenService(databaseControllerMock, loggerMock);

    //TODO prepare expected product fields
    Product expectedProduct = new Product();
    Map<String, Object> map = new HashMap<>();
    map.put("name", expectedProduct.getName());
    map.put("calories", expectedProduct.getCalories());
    map.put("fat", expectedProduct.getFat());
    map.put("carbo", expectedProduct.getCarbo());
    map.put("protein", expectedProduct.getProtein());
    map.put("productKinds", expectedProduct.getProductKinds());
    map.put("author", expectedProduct.getAuthor());
    map.put("media", expectedProduct.getMedia());
    map.put("approved", expectedProduct.getApproved());



    //TODO prepare argument product
    Product productToSave = new Product();
    productToSave.setName("kaszanka");
    productToSave.setCalories(1000);
    productToSave.setFat(40.00);
    productToSave.setCarbo(20.00);
    productToSave.setProtein(40.00);
    productToSave.setProductKinds(Collections.singletonList(ProductKind.MEAT));
    productToSave.setApproved(false);
    Author author = new Author();
    author.setId("testID");
    author.setName("Endrju Golota");
    productToSave.setAuthor(author);
    Media media = new Media();
    media.setMediaType(MediaType.IMAGE);
    media.setName("dupajasia");
    media.setUrl("http://blabla.pl");
    productToSave.setMedia(media);



    UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(primaryKey).withValueMap(map);

    UpdateItemOutcome itemOutcome = databaseControllerMock.getTable("product").updateItem(updateItemSpec);


    when(databaseControllerMock.update(any(Item.class))).thenReturn(itemOutcome);

    Product actualProduct = instance.editProduct(productToSave);

    assertEquals(expectedProduct, actualProduct);

}

I have a lot of problems with tests but I'm still learing how to do that right, don't be unpolite if You see something ridiculous in my code...

You shouldn't assert against something that is unpredictable. Instead of using assertEquals to compare the whole object you can simply test every predictable field with many assertEquals.

The way your editProduct method is right now is not unit-testable. I would break your editProduct method into smaller ones. Something like:

public Product editProduct(PrimaryKey primaryKey, Product content) {

    UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(primaryKey).withValueMap(createMap(content));

    UpdateItemOutcome itemOutcome = databaseController.getTable(PRODUCT_TABLE).updateItem(updateItemSpec);

    return  toProduct(itemOutcome);

}

public Map<String, Object> createMap(Product content) {

    Map<String, Object> result = new HashMap<>();

    result.put("name", content.getName());
    result.put("calories", content.getCalories());
    result.put("fat", content.getFat());
    result.put("carbo", content.getCarbo());
    result.put("protein", content.getProtein());
    result.put("productKinds", content.getProductKinds());
    result.put("author", content.getAuthor());
    result.put("media", content.getMedia());
    result.put("approved", content.getApproved());

    return result;
}

public Product toProduct(UpdateItemOutcome outcome) {

    Product product = new Product();
    product.setName(itemOutcome.getItem().get("name").toString());
    product.setCalories(itemOutcome.getItem().getInt("calories"));
    product.setFat(itemOutcome.getItem().getDouble("fat"));
    product.setCarbo(itemOutcome.getItem().getDouble("carbo"));
    product.setProtein(itemOutcome.getItem().getDouble("protein"));
    product.setProductKinds(itemOutcome.getItem().getList("productKinds"));

    ObjectMapper objectMapper = new ObjectMapper();
    try {
        Author productAuthor = objectMapper.readValue(itemOutcome.getItem().getString("author"), Author.class);
        product.setAuthor(productAuthor);
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        Media productMedia = objectMapper.readValue(itemOutcome.getItem().getString("media"), Media.class);
        product.setMedia(productMedia);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return product;

}

Now you could unit test the smaller methods toProduct and createMap to see if they behave as you expect.

And as you said in your comment in you need to mock the database since this is a unit-test.

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