get_posts works but new wp_query doesn’t

You forget $query->the_post(), which makes the same as setup_postdata(). Also you are using $post->ID inside the loop but $post is not current post object in the loop. You have also syntax errors; for example you pass thumnail to wp_get_attachment_image() instead of a string "thumbnail", and pass name as orderby argument instead of the string "name", or ASC instead of "ASC":

 <?php
 //as you are inside a loop but I don't see $post variable in your code,
 //I assume you want the current post in the loop as parent
 $parent_id = get_the_ID();

 $args = array(
    'post_type' => 'attachment',
    'post_mime_type' => 'image',
    'posts_per_page' => 4,
    'post_status' => 'inherit',
    'post_parent' => $parent_id,
    'orderby' => 'name',
    'order' => 'ASC'
);

$attachments = new WP_Query($args);
while ($attachments->have_posts()) {
       $attachments->the_post();
       //I pass $parent_id to get_permalink() because you was trying
       //to do that in your code but I'm not sure if this is what you want
       ?>
      <a class="postpreview" href="https://wordpress.stackexchange.com/questions/143033/<?php echo get_permalink($parent_id); ?>"><?php echo wp_get_attachment_image(get_the_ID(), 'thumbnail') ?></a>

 <?php
 }
 wp_reset_postdata();
 ?>

Anyway, new WP_query is not much better than get_posts(), each one has its benefits and the better depends on what you want to do.